Ad

Laravel Model Append Attribute From Polymorphic Relation

- 1 answer

I have a model Course as follows:

class Course extends Model {
    protected $table = 'courses';
    protected $primaryKey = 'id';
    public $incrementing = true;
    public $timestamps = false;

    protected $appends = ['locked_by'];

    public function lock(){
        return $this->morphMany('App\Models\Lock', 'asset');
    }

    public function getLockedByAttribute(){
        if($this->lock->count()){
            return $this->lock->shift()->owner_id;
        } else {
            return 0;
        }
    }
}

A Course can have many associated Lock objects indicating that a user wants to lock the Course data for editing by other users.

Now, when retrieving the Course details of a specific course from the Laravel API I get the following data:

    {
        "id": 1,
        "name": "Linear Algebra 2",
        "abbreviation": "2WF20",
        "status": "draft",
        "owner_id": 2,
        "created_at": "2020-03-10 13:09:15",
        "locked_by": 2,
        "lock": []
    }

while I expected:

    {
        "id": 1,
        "name": "Linear Algebra 2",
        "abbreviation": "2WF20",
        "status": "draft",
        "owner_id": 2,
        "created_at": "2020-03-10 13:09:15",
        "locked_by": 2
    }

As you can see in the code the "locked_by" attribute does not come from the Course table but is added by the $appends variable in the model. The number that's after "locked_by" is the user ID of the user currently owning the lock on this Course.

Can anyone tell me where the "lock": [] attribute comes from and how to get rid of it? I noticed myself that "lock": [] attribute is not there if the getLockedByAttribute() function does not access $this->lock, however, I need this reference to get the user_id of the user owning the lock? Am I doing something wrong? Should I use a different approach to get the user_id of the user owning the lock?

Ad

Answer

The lock attribute is in the response because in order to get the value for the locked_by attribute the model needs to load the lock relationship.

If you want to hide the lock relationship every time you return the Course model as an array or JSON you can add the relationship to the $hidden property on your Course model.

From the docs:

Sometimes you may wish to limit the attributes, such as passwords, that are included in your model's array or JSON representation. To do so, add a $hidden property to your model.

When hiding relationships, use the relationship's method name.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Course extends Model
{
    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = ['lock'];
}

If you only want to hide it in a specific request you could do something like this:

return App\Courses::with('lock')
    ->get()
    ->makeHidden('lock');
Ad
source: stackoverflow.com
Ad