I recently saw a question on Laravel Brasil community that turned out to be a lot more interesting than it looks. Imagine you have a
UsersResource with the following implementation:
For some reason you might want to reuse that resource class on another endpoint, but hide the email field. This article is an approach on how to achieve that.
If you have no idea what API Resources are, check out my previous articles on this subject.
1- Setting up the project
The interesting stuff start at section 3.
composer create-project --prefer-dist laravel/laravel api-fields
.env file to remove database settings and use SQLite
Continue setting up the project
php artisan migrate
php artisan make:resource UsersResource
php artisan make:resource --collection UsersResourceCollection
php artisan make:controller UsersController
php artisan tinker
2- The Routes
Make sure to create a route in the
3- The Controller
The Controller represents the desired goal. In this example let’s suppose in the listing we only want the name of all users whereas in the show we want to hide only the email address.
In order to achieve this, we need both our
UsersResourceCollection and our
UsersResource to know how to handle the
4- The UsersResource Class
Let’s start with the
show method. The
UsersResource::make will return an object of
UsersResource. As such, we should expose a method
hide that stores the desired keys to be removed from the response.
Done! At this point we should be able to access
http://api.dev/api/users/1 and se a response without the
"name": "Mr. Frederik Morar",
5- The UsersResourceCollection Class
For a collection of items to work on the
index method, we need to perform a few changes:
- (1) Make sure
UsersResource::collectionreturns an instance of
- (2) Expose the
- (3) Pass through the hidden fields to
For (1), we just need to override the
collection method on
For (2) and (3) we need to change the
UsersResourceCollection file. Let’s expose the
hide method and process the collection with the hidden fields.
And that’s it! Now if we call
http://api.dev/api/users we can see a response without
"name": "Mr. Frederik Morar"
"name": "Angel Daniel"
"name": "Brianne Mueller"
The goal was to make the
Resource class a little flexible by allowing it to hide some fields that another endpoint may expose. An actual example of this implementation would be a
/users endpoint not including the
avatar attribute, but when requesting a specific user via
/users/99 we may desire to include the
avatar in the response.
I wouldn’t recommend reusing API Resources too much as it may easily increase the complexity of a layer that is suppose to be simple. With that said, hiding some specific fields between requests of list and specific record does seem a reasonable request on the account of the simplicity of the implementation.
7- What’s Next
On a next article, I’ll try to extract the
hide method into a trait and make it reusable throughout all of the API Resources. Follow me on Medium to stay tuned!