2

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 ?

2 Answers 2

5

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.

Sign up to request clarification or add additional context in comments.

1 Comment

it doesn't work, "Method Illuminate\Support\Collection::hide does not exist."
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.