Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Eloquent setting a default value for a model relation?

I have two models:

class Product extends Eloquent {

    ...

    public function defaultPhoto()
    {
        return $this->belongsTo('Photo');
    }

    public function photos()
    {
        return $this->hasMany('Photo');
    }
}

class Photo extends Eloquent {

    ...

    public function getThumbAttribute() {
        return 'products/' . $this->uri . '/thumb.jpg';
    }

    public function getFullAttribute() {
        return 'products/' . $this->uri . '/full.jpg';
    }

    ...

}

This works fine, I can call $product->defaultPhoto->thumb and $product->defaultPhoto->full and get the path to the related image, and get all photos using $product->photos and looping through the values.

The problem arises when the product does not have a photo, I can't seem to figure out a way to set a default value for such a scenario.

I have tried doing things such as

public function photos() 
{
    $photos = $this->hasMany('Photo');
    if ($photos->count() === 0) {
        $p = new Photo;
        $p->url = 'default';
        $photos->add($p);
    }

    return $photos;
}

I have also creating a completely new Collection to store the new Photo model in, but they both return the same error:

Call to undefined method Illuminate\Database\Eloquent\Collection::getResults()

Has anyone done anything similar to this?

Thanks in advance!

like image 609
Andrew Willis Avatar asked Mar 21 '23 05:03

Andrew Willis


1 Answers

You could create an accessor on the Product model that did the check for you. Works the same if you just wanted to define it as a method, also (good for if you want to abstract some of the Eloquent calls, use an interface for your Product in case you change it later, etc.)

/**
 * Create a custom thumbnail "column" accessor to retrieve this product's
 * photo, or a default if it does not have one.
 * 
 * @return string
 */
public function getThumbnailAttribute()
{
    $default = $this->defaultPhoto;

    return ( ! is_null($default))
        ? $default->thumb
        : '/products/default/thumb.jpg';
}

You might also want to look into Presenters. A bit overkill for some situations, but incredibly handy to have (and abstract things like this away from your models).

like image 111
Aken Roberts Avatar answered Apr 06 '23 11:04

Aken Roberts