6

I'm trying to get a custom attribute (https://laravel.com/docs/5.5/eloquent-mutators#defining-an-accessor) from a query.

Right now I have:

User.php

public function getViewUrlAttribute()
{
    return route('admin.users.view', ['id' => $this->id]);
}

public function role()
{
    return $this->belongsTo('App\Role')->withDefault([
        'name' => 'User'
    ]);
}

UserController.php

public function dataTable(Request $request)
{
    $length = $request->has('length') ? $request->input('length') : 10;
    $orderDirection = $request->input('orderDirection');
    $searchValue = $request->input('search');

    $users = User::select('id', 'name', 'email', 'created_at')->with('role:name')->limit($length);

    if ($request->has('orderBy')) {
        if ($request->has('orderDirection')) {
            $users = $users->orderBy($request->input('orderBy'), $request->input('orderDirection') > 0 ? 'asc' : 'desc');
        } else {
            $users = $users->orderBy($request->input('orderBy'), 'desc');
        }
    }

    return $users->get();
}

Returns

[
 {
  "id": 1,
  "name": "User",
  "email": "[email protected]",
  "created_at": "2018-04-24 14:14:12",
  "role": {
   "name": "User"
  }
 }
]

So the thing is: there's any way to also get the view_url attribute? (I tried inside the with() but it fails)

Also can I return only the role name and not the whole object as you can see in the "Return" code? (I would like something like: "role": "User").

(Of course I'm trying to avoid running raw sql)

Thanks!

2
  • have you looked at the $appends attribute? protected $appends = ['view_url']; in your User model. Commented Jun 5, 2018 at 16:51
  • you mean sth like with('role:view_url') beside name ? Commented Jun 5, 2018 at 17:00

1 Answer 1

8

You're almost done...

1- To add a custom attribute you need to append it on the Model with $appends attribute:

protected $appends = ['view_url'];

And define your attribute method:

public function getViewUrlAttribute()
{
    return route('admin.users.view', ['id' => $this->id]);
}

2- To add attribute to a model from another related model, I think you should try :

// to add them as attribute automatically
protected $appends = ['view_url', 'role_name'];

// to hide attributes or relations from json/array
protected $hidden = ['role']; // hide the role relation

public function getRoleNameAttribute()
{
    // if relation is not loaded yet, load it first in case you don't use eager loading
    if ( ! array_key_exists('role', $this->relations)) 
        $this->load('role');

    $role = $this->getRelation('role');

    // then return the name directly
    return $role->name;
}

Then you might not event need ->with('role') eager loading.

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

2 Comments

Can't believe I was almost there (stuck on this for hours..) Thank you so much Keitel!
U're welcome! Laravel Docs are very good but does not explain all the details. Laracasts is there for more details, visit Laracasts website and you'll find a lot more for Laravel.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.