samir
samir

Reputation: 199

How to remove some values in collection when using Laravel API Resource

I'm in a blog project. I have this API Resource for my Post model

return [
    'id' => $this->id,
    'title' => $this->title,
    'body' => $this->body,
    'date' => $this->date
];

but I don't want to get 'body' => $this->body when I get collection of Posts, because I only use it when I want to show the post, not for listing them

How can I do that ? should I use Resource Collections ?

UPDATE: makeHidden should work, but it doesn't because we have Illuminate\Support\Collection instead of Illuminate\Database\Eloquent\Collection, how can I make a cast or make API resource's collection method to return an Illuminate\Database\Eloquent\Collection instance ?

Upvotes: 2

Views: 5227

Answers (2)

Ashutosh Kamble
Ashutosh Kamble

Reputation: 193

There is a method for conditionally adding attribute to resource as shown below

return [
    'attribute' => $this->when(Auth::user()->isAdmin(), 'attribute-value'),
];

I hope this will help you

Upvotes: 1

fakorede
fakorede

Reputation: 783

I assume you have a PostResource, if you don't you can generate one:

php artisan make:resource PostResource

Override the collection method on PostResource and filter fields:

class PostResource extends Resource
{
    protected $withoutFields = [];

    public static function collection($resource)
    {
        return tap(new PostResourceCollection($resource), function ($collection) {
            $collection->collects = __CLASS__;
        });
    }

    // Set the keys that are supposed to be filtered out
    public function hide(array $fields)
    {
        $this->withoutFields = $fields;
        return $this;
    }

    // Remove the filtered keys.
    protected function filterFields($array)
    {
        return collect($array)->forget($this->withoutFields)->toArray();
    }

    public function toArray($request)
    {
        return $this->filterFields([
            'id' => $this->id,
            'title' => $this->title,
            'body' => $this->body,
            'date' => $this->date
        ]);
    }
}

You need to create a PostResourceCollection

php artisan make:resource --collection PostResourceCollection 

Here the collection is being processed with the hidden field(s)

class PostResourceCollection extends ResourceCollection
{
    protected $withoutFields = [];

    // Transform the resource collection into an array.
    public function toArray($request)
    {
        return $this->processCollection($request);
    }

    public function hide(array $fields)
    {
        $this->withoutFields = $fields;
        return $this;
    }
    // Send fields to hide to UsersResource while processing the collection.
    protected function processCollection($request)
    {
        return $this->collection->map(function (PostResource $resource) use ($request) {
            return $resource->hide($this->withoutFields)->toArray($request);
        })->all();
    }
}

Now in PostController you can call the hide method with the field to be hidden:

public function index()
{
    $posts = Post::all();
    return PostResource::collection($posts)->hide(['body']);
}

You should get a collection of Posts without the body field.

Upvotes: 5

Related Questions