Reputation: 447
In the new Laravel Resource classes, you are able to remove attributes based on anything you like.
If you want to return many items, you can use the function
Resource::collection()
But that does not let you add metadata in one place. Enter a Collection, great, this is many items in a nice format with the ability to add meta data. What you cannot do though, is filter the collection you have to hide attributes like you can with a resource. The only way I can see to do it is
foreach ($this->collection as $item) {
if ($notAdmin) {
$temp = array_except($item->toArray(), ['secret']);
}
$temp['links'] = ['self' => route('restaurant.show', [$item])];
$data[] = $temp;
}
Is there something I am missing? This seems like a massive overlooked ability for a Resource Collection
Upvotes: 4
Views: 8222
Reputation: 14271
Based in this thread, it seems that when using a ResourceCollection class to customize a collection (for example BookCollection
) Laravel look up for a Resource
class named the same but without the Collection sufix class (in the example, a class named just Book
).
So you will need to have a resource class named: Book
where you customize the attributes to be returned to the response and a collection class named: BookCollection
, that will use Book
-to customize the data- and will also let you customize the metadata.
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class Book extends Resource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
];
}
}
<?php
namespace App\Http\Resources\Users;
use Illuminate\Http\Resources\Json\ResourceCollection;
class BookCollection extends ResourceCollection
{
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request
* @return array
*/
public function toArray($request)
{
return $this->collection;
}
public function with($request)
{
return [
'meta' => [
'key' => 'value',
],
];
}
}
Upvotes: 9
Reputation: 9962
Ok, here's how you do it:
Create a Resource
for a single resource, where you can easily have conditional attributes
Create a RCollection
for the collection, where you can add meta data.
Pass the Resource::collection(Model::all)
into the new RCollection()
.
Something like this (from my testing):
Route::get('users/all', function() {
return new \App\Http\Resources\Users(
\App\Http\Resources\UserResource::collection(\App\User::get())
);
});
Works like a charm!
Upvotes: 0