laravel resource collection has blank output - laravel

I am trying to get a json output of a collection but all I am getting is a data [].
I have 2 tables.
TABLE:Player ||
id |
name
and
TABLE:FlightTime || id | vehicle | totaltime | player_id (foreign key)
I am trying to get all the flighttime entry for a particular player as a collection.
My FlightTime resource:
class FlightTime extends JsonResource
{
public function toArray($request)
{
return [
'vehicle' => $this->vehicle,
'total-time' => $this->totaltime,
];
}
}
And my FlightTimeCollection:
class FlightTimeCollection extends ResourceCollection
{
public function toArray($request)
{
return [
'data' => $this->collection,
'test' => 'did this work',
];
}
}
My api route is set as
Route::get('/v1/player/{name}/flights', 'PlayerController#showFlightbyName');
And I have this in my controller:
public function showFlightbyName($name)
{
$pid = Player::select('id')->where('name', $name)->first();
return new FlightTimeCollection(FlightTime::where('player_id', $pid)->get());
}
Now when I visit localhost/api/v1/player/Angel/flights, No error is thrown. But all I am getting is this.
{
"data": [],
"test": "did this work"
}
I just can't figure out what's going on here and what I did wrong.

You should treat the toArray() method in your FliightTimeCollection the same way you treat it in FlightTimeResource. The collection will be automatically wrapped in data => [stuff]'.
So, like this:
class FlightTimeCollection extends ResourceCollection
{
public function toArray($request)
{
return [
'vehicle' => $this->vehicle,
'another_field' => $this->field2,
// ...
];
}
}
Result of that would be
{
"data": [
{"vehicle": "some value", "another_field": "some value"},
// ...
],
}

I got it working. $pid is an obj and I needed to get the value out of $pid->id
public function showFlightbyName($name)
{
$pid = Player::select('id')->where('name', $name)->first();
return new FlightTimeCollection(FlightTime::where('player_id', $pid->id)->get());
}

Related

How to insert Custom row Laravel excel collection

I trying to export a Excel file, from a collection using laravel. The code bellow, returns me this. I need to add a 2 new rows above the start of columsn, is that possible? What Should I do?
<?php
namespace App\Traits;
namespace App\Exports;
// use Illuminate\Support\Collection;
use Illuminate\Database\Eloquent\Collection;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithColumnWidths;
use Maatwebsite\Excel\Concerns\WithStyles;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
class exportSafety implements FromCollection, WithHeadings, WithMapping, WithColumnWidths, WithStyles, WithColumnFormatting, WithCustomStartCell
{
protected $services;
protected $request;
public function __construct(Collection $services)
{
$this->services = $services;
}
public function startCell(): string
{
return 'A3';
}
public function columnWidths(): array
{
return [
'A' => 30,
'B' => 20,
'C' => 20,
'D' => 15,
];
}
public function columnFormats(): array
{
return [
'B' => NumberFormat::FORMAT_DATE_DDMMYYYY,
];
}
public function styles(Worksheet $sheet)
{
return [
// Style the first row as bold text.
3 => ['font' => ['bold' => true]],
];
}
public function collection()
{
$this->services->each(function ($service) {
$this->map($service);
});
return $this->services;
}
public function headings(): array
{
$columns = [
'Name' => 'Name',
'Data de Nascimento' => 'Data de Nascimento',
'CPF' => 'CPF',
'Valor do Seguro' => "Valor do Seguro"
];
return $columns;
}
public function startRow(): int
{
return 2;
}
public function map($service): array
{
$columns = [
'Name' => $service->name,
'Data de Nascimento' => $service->birthdate,
'CPF' => $service->cpf,
'Valor do Seguro' => $service->client->donation_safety
];
return $columns;
}
}
But I need something like this:
I need to put two custom row above the start of the columns, is that possible? How I to that? I am using https://docs.laravel-excel.com/3.1/imports/multiple-sheets.html
you need to use WithHeadings trait to format heading rows.
$rangeHeadings = [
'chiqaruvchi',
'chiqarilgan',
'sotilgan',
"sana",
];
public function headings(): array
{
return [
[
$this->product?->name . " product " . $this->params['from_date'] . ' - ' . $this->params['to_date'] . " report",
],
$rangeHeadings,
];
}

Laravel / OctoberCMS frontend filter

I am using OctoberCMS and I have created a custom component. I am trying to create a frontend filter to filter Packages by the Tour they are assigned to.
This is what I have so far. The issue is that the code is looking for a tour field within the packages table rather than using the tour relationship. Does anyone have any ideas?
<?php namespace Jakefeeley\Sghsportingevents\Components;
use Cms\Classes\ComponentBase;
use JakeFeeley\SghSportingEvents\Models\Package;
use Illuminate\Support\Facades\Input;
class FilterPackages extends ComponentBase
{
public function componentDetails()
{
return [
'name' => 'Filter Packages',
'description' => 'Displays filters for packages'
];
}
public function onRun() {
$this->packages = $this->filterPackages();
}
protected function filterPackages() {
$tour = Input::get('tour');
$query = Package::all();
if($tour){
$query = Package::where('tour', '=', $tour)->get();
}
return $query;
}
public $packages;
}
I really appreciate any help you can provide.
Try to query the relationship when the filter input is provided.
This is one way to do it;
public $packages;
protected $tourCode;
public function init()
{
$this->tourCode = trim(post('tour', '')); // or input()
$this->packages = $this->loadPackages();
}
private function loadPackages()
{
$query = PackagesModel::query();
// Run your query only when the input 'tour' is present.
// This assumes the 'tours' db table has a column named 'code'
$query->when(!empty($this->tourCode), function ($q){
return $q->whereHas('tour', function ($qq) {
$qq->whereCode($this->tourCode);
});
});
return $query->get();
}
If you need to support pagination, sorting and any additional filters you can just add their properties like above. e.g;
protected $sortOrder;
public function defineProperties(): array
{
return [
'sortOrder' => [
'title' => 'Sort by',
'type' => 'dropdown',
'default' => 'id asc',
'options' => [...], // allowed sorting options
],
];
}
public function init()
{
$filters = (array) post();
$this->tourCode = isset($filters['tour']) ? trim($filters['tour']) : '';
$this->sortOrder = isset($filters['sortOrder']) ? $filters['sortOrder'] : $this->property('sortOrder');
$this->packages = $this->loadPackages();
}
If you have a more complex situation like ajax filter forms or dynamic partials then you can organize it in a way to load the records on demand vs on every request.e.g;
public function onRun()
{
$this->packages = $this->loadPackages();
}
public function onFilter()
{
if (request()->ajax()) {
try {
return [
"#target-container" => $this->renderPartial("#packages",
[
'packages' => $this->loadPackages()
]
),
];
} catch (Exception $ex) {
throw $ex;
}
}
return false;
}
// call component-name::onFilter from your partials..
You are looking for the whereHas method. You can find about here in the docs. I am not sure what your input is getting. This will also return a collection and not singular record. Use ->first() instead of ->get() if you are only expecting one result.
$package = Package::whereHas('tour', function ($query) {
$query->where('id', $tour);
})->get();

syntax error, unexpected ',', expecting ']'

I'm trying to add data into db with all first words as capital letter. But it's shows error syntax error.
unexpected ',', expecting ']',,,,,,,,,,,,,,,,,,,
Model
protected $fillable = [
'category_name',
'category_description',
'category_slug',
'category_image'
];
public function setFirstNameAttribute($value)
{
$this->attributes[
'category_name',
'category_description',
'category_slug',
'category_image'
] = strtoupper($value);
}
Your usage of setFirstNameAttribute($value) mutator function is wrong. Mustator is only for one attribute. So you have to create multiple mutators for every attribute.
Possible answer. If you want to mutate category_name.
public function setCategoryNameAttribute($value)
{
$this->category_name = strtoupper($value);
}
And if you want to mutate category_description
public function setCategoryDescriptionAttribute($value)
{
$this->category_description = strtoupper($value);
}
likewise you need to define multiple mutators to all the other attributes.
EDIT
if you want to make only to capitalize the first letter of words use title_case() instead of strtoupper()
public function setCategoryDescriptionAttribute($value)
{
$this->category_description = title_case($value);
}
Try it.
public function setCategoryNameAttribute($value){
$this->attributes['category_name'] = strtoupper($value);
}
Or
public function setCategoryNameAttribute($value)
{
return strtoupper($value);
}
If you want to do with all field then you may have define the function for all.
$this->attributes[
'category_name',
'category_description',
'category_slug',
'category_image'
] = strtoupper($value);
You can't set multiple array values at once like this. You would have to set them separately or in a loop:
public function setFirstNameAttribute($value)
{
$attribute_names = [
'category_name',
'category_description',
'category_slug',
'category_image',
];
foreach ($attribute_names as $attribute_name) {
$this->attributes[$attribute_name] = strtoupper($value);
}
}

laravel - change value in array for API Resources

{
"data": {
"username": "candy",
"certificates": [
{
"id": 11,
"category_id": 1,
"certname": "cert name test",
"created_at": "2018-08-18 00:58:12",
"updated_at": "2018-08-18 00:58:12"
}
]
}
}
Above is a response by using Eloquent: API Resources.
I would like to put category name instead of category_id.
Below is resource class
public function toArray($request)
{
return [
'nickname' => $this->nickname,
'certificates' => $this->certificates,
];
}
certificates are in array (hasMany relationship)
certificates belongsTo category
In this case, in the resource class you can fetch category name for each certificate and attach it.
public function toArray($request)
{
$certificateList = $this->certificates;
foreach($certificateList as $ceritificate) {
// fetch only the category name from the database.
// attach to the certificate.
$categoryName = Category::where('id', $certificate->category_id)->pluck('name')->first();
$certificate->setAttribute('category_name, $categoryName);
}
// then as usual
return [
'nick_name' => $this->nick_name,
'certificates' => $certificateList
];
}
This Might Help,
Run a foreach loop
$category = "Your SELECT Query";
foreach ($category as $value) {
$categoryId = json_decode($value->category_id);
$x = Category::select('certname')->whereIn('id', $categoryId)->get();
foreach ($x as $as) {
$y[] = $as->certname;
}
$value->certname = $y;
you can just do it like this
in controler
return CertificateResource::collection(Certificate::with('category')->get());
in CertificateResource
return [
'nickname' => $this->nickname,
'certificates' => $this->certificates,
'category_name'=>$this->whenLoaded('category', function () {
return $this->category->category_name;
}),
];

Yii2- get from related table name to add to Sluggable

Yii2. How can i get data from the related table and add it to Sluggable behavior.
In the example below, I want for every book add slug-title like "Book House, author Greenberg".
class Books extends \yii\db\ActiveRecord
{
public function behaviors()
{
return [
[
'class' => SluggableBehavior::className(),
'attribute' => "Book" . $this->name . ", author " . $this->getAuthor->name,
//'slugAttribute' => 'slug',
],
];
}
public function getAuthor()
{
return $this->hasOne(Author::className(), ['id' => 'author_id']);
}
}
Simply use a callback for the sluggable behavior like so:
public function behaviors()
{
return [
[
'class'=>SluggableBehavior::className(),
'value'=>function ($event) {
$parts = ['Book', $this->name, 'author', $this->author->name];
return Inflector::slug(implode('-', $parts));
},
],
];
}
My example will output a slug like this: book-house-author-greenberg which is more best practice for slugs than your version. Anyway...if you still prefer the way you described above, simply change the return value.
The doc for the feature used in my example is here.

Resources