In laravel 8 app when in pagination request I use mapping with calculated new field :
$hostelDataRows = Hostel
::orderBy('created_at', 'desc')
->where('hostels.id', 41) // debug
->with('state')
->with('region')
->with('user')
->withCount('hostelRooms')
->withCount('hostelInquiries')
->withCount('hostelImages')
->getByName($this->filters['name'], true)
->getByStatus($this->filters['status'], true)
->getByStateId($this->filters['state_id'], true)
->getByFeature($this->filters['feature'], true)
->addSelect([
'min_hostel_rooms_price' =>
HostelRoom::query()
->selectRaw('MIN(price)')
->whereColumn('hostel_id', 'hostels.id'),
])
->paginate($backend_per_page)
->map(function ($hostelItem) {
if ($hostelItem->hostel_rooms_count > 0 and $hostelItem->hostel_inquiries_count > 0 and $hostelItem->hostel_images_count > 0 ) {
$hostelItem->info_text = 'Has ' . ($hostelItem->hostel_rooms_count . pluralize3( $hostelItem->hostel_rooms_count, 'no rooms', 'room', 'rooms' ) );
}
return $hostelItem;
})
;
I got error :
Method Illuminate\Database\Eloquent\Collection::links does not exist. (
it is clear that with mappimg $hostelDataRows is not pagination object anyway...
How that can be fixed ?
Thanks!
CodePudding user response:
When you use map()
on a Paginator instance, you will get a Collection
instance back (I think it is Illuminate\Database\Eloquent\Collection
here). So you can't put map()
in front of it since that would require you to fetch the query (which is dependent on the paginator page). However there are some other solutions:
Solution 1: use the tap()
helper
The tap()
helper always returns the argument to the function. Since Collection map()
(and transform()
which is very similar) modify the instance Collection itself, this works as intended and you now get your original paginator instance back (with the extra properties from your map-function).
return tap($query->paginate())->map(...);
Solution 2: use a getInfoTextAttribute()
accessor
In your specific usecase you might just as well make a property for your $hostelItem
if you are going to use this property more often, like so:
// Models/HostelItem.php
/**
* @property string $info_text
*/
class HostelItem extends Model
{
public function getInfoTextAttribute()
{
return 'Has ' . ($this->hostel_rooms_count . pluralize3( $this->hostel_rooms_count, 'no rooms', 'room', 'rooms' ) );
}
}
I've added a @property
annotation so you can have code assist in most of your files. Now, simply call $hostelItem->info_text
and you're done. no need for a map.