Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5 Eloquent appending relationships to JSON on multiple levels

So it is pretty easy to include relationships on models such as:

class User extends Model {
     protected $with=['roles']
}

class Role extends Model {
     protected $with=['permissions']
}

when there's a get request to the user resource, it will include associated roles automagically.

But in this setup, the role resources returned with user resource also includes it's own included relationships like:

{user:{id:1, roles:[{id:1, permissions:[{id:1..

This generates huge objects, that mostly include unnecessary related child models.

I can workaround this by setting attributes to replace the default relationship includes but the API i am working on has 30+ resources and that path isn't the ideal beause it will require me to write a lot of repeated code on models.

is there a way to manage the depth of appended relationships easily?

i imagine something like:

class Role extends Model {
     protected $with=['permissions'];
     protected $includeWith=[]; // role wont have the permissions appended when included
}
like image 934
Varol Avatar asked Apr 10 '15 11:04

Varol


2 Answers

Instead of the built-in '$with' array, you could roll your own attribute using $appends:

class User extends Model
{
    protected $appends = ['roles_list'];

    // ...
    // other stuff here, like relationship definitions
    // ...

    public function getRolesListAttribute()
    {
        return $this->roles;
        //OR build 'roles_list' manually, returning whatever you like.
    }
}

The only downside is you have to look out for 'roles_list' instead of 'roles', on the receiving end.

like image 162
Robert Avatar answered Nov 13 '22 13:11

Robert


If somebody is still interested in a solution for this: Laravel 5.5 introduced Api Resources which is a great way to organize the api responses. Just don't include any relationships on your model and append them on the resource.

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\Resource;

class UserResource extends Resource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
            'roles'=> $this->roles

        ];
    }
}
like image 45
Varol Avatar answered Nov 13 '22 14:11

Varol