I had this same problem and was confused because in the documentation it says:
You may pass a Laravel paginator instance to the collection method of a resource or to a custom resource collection... Paginated responses always contain meta and links keys with information about the paginator's state (Laravel 6 docs).
The problem is that these resource objects are designed to be returned directly rather than included in a larger JSON response. See my thoughts on why this is happening, here.
There's two ways you could solve this problem.
Solution 1
Eliminate the meta data being sent along with the response (the 'code', and 'success' fields). These are somewhat redundant because when the JSON resource is returned, it will be sent with an HTTP response who's status is 200 OK
. Code that is consuming your API should be able to parse both the status and the status message. Your controller function would now look like this:
public function index()
{
return new DataResource::collection(Customers::with('order')->paginate(10))
}
Solution 2
If the consumers of your API absolutely rely on the meta data your sending along, Laravel has a solution for that. Laravel provides a ResourceCollection
class which can include arbitrary meta data.
While resources translate a single model into an array, resource collections translate a collection of models into an array. It is not absolutely necessary to define a resource collection class for each one of your model types since all resources provide a collection method to generate an "ad-hoc" resource collection on the fly. However, if you need to customize the meta data returned with the collection, it will be necessary to define a resource collection.
Begin by modifying your DataResource
to extend Illuminate\Http\Resources\Json\ResourceCollection
instead of Illuminate\Http\Resources\Json\Resource
. You can then add meta data to the response in any of 3 ways. 1) By adding it to the array returned by the toArray()
function. 2) Defining a with()
function on the collection resource that is called when the resource is returned from a controller function. Or 3) append it to the resource when creating the collection (see docs). I'm going to show option 2 because it's only called when the collection is returned as the outer most resource.
Resource
use Illuminate\Http\Resources\Json\ResourceCollection;
class DataCollection extends ResourceCollection
{
public function toArray($request)
{
return [
'name' => $this->name,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'order' => Resources::collection($this->order)
];
}
public function with($request)
{
return [
'meta' => [
'success' => 'true',
'code' => 0,
],
];
}
Controller
use App\Http\Resources\DataCollection;
public function index()
{
return new DataCollection(Customers::with('order')->paginate(10));
}
Renaming your resource is optional, but matches convention. Meta tags you define will be merged with the meta tags created by the paginator.
This functionality has been in place since at least Laravel 6.X. Check docs for earlier compatibility if needed.