edgreenberg's avatar

Illuminate Pagination

Somewhere between 5.8 and 6.0, PaginatedResourceResponse::toResponse() changed.

In 5.5, in an API controller, I did a query and passed it to ->paginate($num) instead of to get() and then pushed the result set into a new ApplicationCollectionResource();. The result of that (a resource) was then returned.

This would work.

In 6.0, when the resource is returned. it winds up in PaginatedResourceResponse::toResponse where the return is $item->resource, while $item is an array, not a collection. This is what changed between 5.8 and 6.0.

I've seen no examples of how to do this in 6.0 or better. My resource has a toArray() function, and I've seen hints in postings about a collection() method, but I have no example of how to write one. Note that the superclass, ResourceCollection, does not define a collection method as an alternative to the toArray method.

Can somebody point me to a >=6.0 example of doing a query and returning the result set in a using Illuminate\Http\Resources\Json\PaginatedResourceResponse?

I have in my controller:

    public function newrecords(Request $request)
    {
    
        // get some records
        
        $datarecords = MyData::where('status','new')->pagenate(50);
        
        // this returns an \Illuminate\Pagenation\LengthAwarePaginator object
        
        $resource = new MyResource($datarecords)
        
        // Now we return the resource:
        
        return $resource;
    }

and my resource contains

    public function toArray($request)
    {
        $result = $this->collection->transform(function ($o) {
            return[
			'key' => $o->value,
			...
                ];
        })->toArray();

        return $result;
    }
0 likes
7 replies
martinbean's avatar

@edgreenberg I’m not sure what you’re pointing out as having changed without seeing a “before” and “after”, but when working with collections you should be passing it to the a collection method on the resource class:

$datarecords = MyData::where('status','new')->paginate(50);

return MyResource::collection($datarecords);

That will return the items in the paginator, along with consistent pagination metadata.

edgreenberg's avatar

This is exactly what I am looking for. Can you point me to an example of a collection method? This is never shown in the docs, only the toArray method. Also, there is no collection method in the superclass. So I'm stumped as to calling and returning parameter types.

edgreenberg's avatar

Thank you, sir. I'll give it a try. (It wasn't where I was looking.)

edgreenberg's avatar

Hi Martin. Again, thanks for engaging withme on this.

I'm still a bit lost. I have an Eloquent query with relations, and a resource with a toArray method that adds the retrieved relation data to the result array for each member of the returned collection. (It uses a call to $this->collection->transform to iterate over the collection. That's left over from 5.5.

When I call

        $resource = ApplicationCollectionResource::collection($applications);

instead of

        $resource = new ApplicationCollectionResource($applications);

and then return $resource, I get:

BadMethodCallException: Call to undefined method Illuminate\Database\Query\Builder::transform() in file /var/www/html/centraladmin/vendor/laravel/framework/src/Illuminate/Support/Traits/ForwardsCalls.php on line 50

Also, I don't think that the returned resource from ApplicationCollectionResource::collection() has any data in it.

Do I have to subclass collection and put my transformations in there, instead of in toArray?

Does my data still pass through toArray?

Sorry to be so confused.

Many thanks, Ed

edgreenberg's avatar

It is the length aware paginator that I am using.

Please or to participate in this conversation.