1

I wonder what are the best practices that the community have about the architecture of Laravel's Resources.

I started using it to avoid sending unnecessary data to certain routes of the API.

I structured it the way my API routes looks like, with specific namespaces corresponding to the routes.

However, doing this faced me to a conceptual problem which is that it forces me to duplicates a lot of Resources that often returns the same data.

For example, if I get a route users/user returning a Resources\Users\User UserResource that would return :

return [
            'id' => $this->id,
            'name' => $this->name,
            'firstname' => $this->firstname,
            'fullName' => $this->fullName(),
        ];

And then create another route named holiday/user, I would create the same resource under namespace Resources\Holiday\ or something like that.

Should I create some global folder for example Users in which I would have different representations of a User, and then pick them depending on my route's use case?

But doing this might involve that I sometimes got data I won't need.

I wonder what are the community's best practices on this subject?

7
  • From my experience it is easier and more convenient to make one size fits all solution. One resource per model, one model per table. Commented Aug 23, 2023 at 12:17
  • But by doing this, ain't you returning data that has nothing to do with the route ? For example you could search for holiday, in which you would have a user, which would have contracts, which would have salary informations for example ? Commented Aug 23, 2023 at 12:20
  • Create seperate resources for those things called SalaryResource or UserSalaryResource. Then have seperate url's for those or included them in the UserResource. Secondly also filtering of which keys to includes on resources is a possibility to similar to what graphql have of features. The problem here is you are seeking a best practice on something that is design and therefor is up for debate. Laravel does'nt dictate how you structure your resources, just provide the resource as a tool. Commented Aug 23, 2023 at 20:35
  • There's no community best practice established here both approaches of "organise resources based on route/model" or "model/route" are equally valid (assuming you are consistent). I don't understand the I sometimes got data I won't need part of your question though so I suspect there may be information that you are not providing Commented Aug 24, 2023 at 7:14
  • I think mrhn got it when speaking about creating separated resource for every model. Then when calling the route /user , you would have only the UserResource returned, in which you wouldn't retrieve any of its relations and then have another route for example user/contract to retrieve each contract you would need. This way it avoid to return automatically the contract of user whenever you need to retrieve a user to display a name for example. apokryofs, what I meant is that sometimes I just need the name of a user, but I retrieve all of its relation. It could retrieve almost complete DB ! Commented Aug 24, 2023 at 9:07

2 Answers 2

4

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:

  1. Showing a list of that resource (A preview if you will)
  2. 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!

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

Comments

1

What I like to do is organize my resources by model and route action. For example, for a User model, I have the following:

    Resources\User\UserIndexResource.php // Lists of users
    Resources\User\UserEditResource.php // Edits a user
    Resources\User\UserShowResource.php // Displays a user

If I need a specific resource for a relation like $holiday->user, I simply add it to the holiday resources:

    Resources\Holiday\HolidayUserResource.php

These organized resource files help me maintain a clear and structured approach to handling different model actions and relationships.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.