This is what I came up with on an enterprise product. (And it works really well.)
I realized that there are only two cases in which I'm using my resource classes:
- Showing a list of that resource (A preview if you will)
- Showing all the necessary details of that resource.
In this case, I created 2 separate resource classes for every model.
For example, if I wanted to do this for my User model, I would create a Minor and a Major resource class under App\Http\Resources\User; so it would be like this:
- app
-- Http
--- Resources
---- User
----- Minor.php
----- Major.php
The Minor class is only used for cases that you need a few properties from the User class; and the Major class is used for the cases that you need all the important properties.
For example, if you send a GET request to api/users you would expect a list of users with name, email and avatar. You don't need all the properties in the database, so you would use the Minor class; but if you send a GET request to api/users/1, you expect to see much more information than before, right? So in this case you want to use Major class, which has more properties like name, email, avatar, date_of_birth, marital_status and blu_blu_blu.
This way of structuring really helps you when the project is getting bigger. Imagine you have an Order class, which has a one to many relationship with the User class; and you want to send a GET request to api/orders; you expect to see a list of orders and their users, right?
In this case, you could use the Minor class of User model inside the Minor class of Order model to show their relationship! Right?
<?php
namespace App\Http\Resources\Order;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\User\Minor as MinorUserResource; // -----> User's minor class
class Minor extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'serial' => $this->serial,
'status' => $this->status,
'created_at' => $this->created_at,
'user' => $this->relationLoaded('user') ?
MinorUserResource::make($this->user) : // -----> Hey look at how I used this class here!
null
];
}
}
Using this approach, your data is consistent, and if you want to make a change in one class, that change will be reflected in other classes as well, and you will have created a nice experience in your API.
Note that this is NOT a best practice of any kind; this is what I thought of on my own. I'd be glad if anyone can make this better.
Cheers!