Ahmad Badpey
Ahmad Badpey

Reputation: 6612

prevent automatically append a relation when using accessor

Suppose we have a Product model like this :

class Product extends Model
{
    protected $appends = ['picture'];

    public function getPictureAttribute()
    {
        $picture = NULL;
        if (!$this->images->isEmpty()) {
            $picture = $this->images->where('selected', TRUE)->first()->path;
        }
        return $picture;
    }

    public function images()
    {
        return $this->morphMany(Image::class, 'imageable');
    }
}

In the other hand there is an Image model like this :

class Image extends Model
{
    protected $fillable = ['title', 'path', 'imageable_id', 'imageable_type', 'selected'];

    public function imageable()
    {
        return $this->morphTo();
    }
}

As you can see each product can have many images. one of those images can be selected as default and now I want when fetch a Product,that be include a picture field that holds path of that selected image. for this I appended a picture attribute to Product model as an accessor.

But each time I call a specific product for example in show controller method like this :

public function show(Product $product)
{
    return $product;
}

Result is like this (a images property is included automatically ) :

{
    "product_id": 1,
    "code": null,
    "created_at": "2017-12-11 12:21:49",
    "updated_at": "2018-01-23 09:38:38",
    "deleted_at": null,
    "picture": "path 2",
    "images": [
        {
            "id": 9,
            "title": "salam",
            "path": "path 1",
            "imageable_id": 1,
            "imageable_type": "Modules\\Product\\Entities\\Product",
            "selected": 0,
            "created_at": "2018-01-23 09:38:38",
            "updated_at": "2018-01-23 09:38:38"
        },
        {
            "id": 10,
            "title": "in the name of god",
            "path": "path 2",
            "imageable_id": 1,
            "imageable_type": "Modules\\Product\\Entities\\Product",
            "selected": 1,
            "created_at": "2018-01-23 09:38:38",
            "updated_at": "2018-01-23 09:38:38"
        }
    ],
    "title": "Updataed Title"
}

I don't know what is problem and how can I solve that.

Upvotes: 1

Views: 131

Answers (2)

Luceos
Luceos

Reputation: 6720

The cause of the images relationship being shown is because it's part of the Model attributes once you retrieve it within the picture accessor.

One of the better practices in my opinion is using transformers which control the data shown in the api response. League fractal offers such functionality. What a transformer does is filter the output; much like an outward middleware. Transformers also offer the ability of includes, allowing you to only show specific data when specifically requested.

Upvotes: 1

Sohel0415
Sohel0415

Reputation: 9853

You can use unset()-

 public function getPictureAttribute()
{
    $picture = NULL;
    if (!$this->images->isEmpty()) {
        $picture = $this->images->where('selected', TRUE)->first()->path;
    }
    unset($this->images);
    return $picture;
}

unset your key before returning.

Upvotes: 2

Related Questions