Gijs Beijer
Gijs Beijer

Reputation: 624

Overriding a Laravel Eloquent Model in an accessor returns 0 on using a property

Sorry for the (maybe) somewhat unclear questioning. I didn't know how to put it in any other way. (suggestions are welcome :p) The code however speaks for itself I think:

I'm using an accessor to get the Theme of a Page (or from its parent if it doesn't have a theme set) as such:

public function getThemeAttribute()
{
    if(!isset($this->theme_uid) || $this->theme_uid === null || $this->theme_uid === '')
    {
        return $this->parent->theme()->first();
    }

    //return $this->theme->first();
    return self::theme()->first();
}

This does work if I'm requesting the theme property itself eg.:

$page->theme

Which returns:

Theme {#741 ▼ ...etcetera

But if I try to access a property on the returned model eg:

$page->theme->uid

I get:

0

Probably has something to do with what happens under the hood, but haven't figured it out yet, so any help would be great.

Thanks already!

Regards Gijs

Upvotes: 1

Views: 1440

Answers (2)

Gijs Beijer
Gijs Beijer

Reputation: 624

Ok, so the method I went with is the following:

public function getThemeAttribute()
{
    if(!isset($this->theme_uid) || $this->theme_uid === null || $this->theme_uid === '')
    {
        return (object)$this->parent->theme()->first()->getAttributes();
    }

    return (object)self::theme()->first()->getAttributes();
}

This allows me to have a nice syntax where I need to access the values (eg: $page->theme->uid or $page->theme->color without having to worry if it is on the parent or what kind of type (Relation, Model, etc) the returned value on theme is.

If somebody can tell me why this isn't directly possible I'm still very interested, and anybody who helped here: Thanks!

Upvotes: 0

Andrius Rimkus
Andrius Rimkus

Reputation: 653

Ok, so as a small code improvement:

(!isset($this->theme_uid) || $this->theme_uid === null) === !isset($this->theme_uid)

isset — Determine if a variable is set and is not NULL

Now this part:

return $this->theme->first();

Will lead to magic method __get recursion and throw an exception. https://bugs.php.net/bug.php?id=71254

In your case, theme is a relationship, not an attribute. I think attribute accessors should be used for their intended purpose - attribute access mutation. You could express your situation via custom relationship:

public function availableTheme()
{
    if(!empty($this->theme_uid))
    {
        return $this->theme();
    }

    return $this->parent->theme();
}

// $page->availableTheme
// $page->avalaibleTheme()->where(...)->first()

Upvotes: 3

Related Questions