skip to Main Content

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 ResourcesUsersUser 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 ResourcesHoliday 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?

2

Answers


  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:

        ResourcesUserUserIndexResource.php // Lists of users
        ResourcesUserUserEditResource.php // Edits a user
        ResourcesUserUserShowResource.php // Displays a user
    

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

        ResourcesHolidayHolidayUserResource.php
    

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

    Login or Signup to reply.
  2. 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 AppHttpResourcesUser; 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 AppHttpResourcesOrder;
     
    use IlluminateHttpRequest;
    use IlluminateHttpResourcesJsonJsonResource;
    use AppHttpResourcesUserMinor 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!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search