Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

PacoW's avatar
Level 1

Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation

Hi all. I do know what this error message means: you forgot () somewhere. But I can't find it anywhere inside my code, and the stack trace doesn't show me where I'm wrong...

LogicException in HasAttributes.php line 403: Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation

It refers to a variable or function called "name" in my User model, so something must be wrong here:

public function nameOrUsername()
    {
        if ($name = $this->name()) {
            return $name;
        } else {
            return "@$this->username";
        }
    }

    public function name()
    {
        if ($this->first_name || $this->last_name) {
            return "$this->first_name $this->last_name";
        } else {
            return null;
        }
    }

It's like Twitter. A user has a username and it's displayed with a '@' in front of it, but it's stored without the at-sign. A user may or may not have a first name and/or last name. So when I want to welcome the user or show the name in the menubar I want to call nameOrUsername(). If the user has a first name and/or last name, that is returned. Else the username (with the @) is returned. I feel so stupid, I can't find the error. The error seemed to come up when pulled from my git repository after re-installing my OS. I tried PHP 5.6 and 7.0 while I was using PHp 7.1 before this, but that can't be the problem?

0 likes
7 replies
PacoW's avatar
Level 1

Oh I forgot. The error occurs when different things happen, nothing to do with this name thing. It's a mystery.

lara65535's avatar
public function nameOrUsername()
    {
        if ($name = $this->name()) {
            return $name;
        } else {
            return "@" . $this->username;
        }
    }

public function name()
    {
        if ($this->first_name || $this->last_name) {
            return "" . $this->first_name . " " . $this->last_name;
        } else {
            return null;
        }
    }

You cant access variables like that inside of the string. You must access the object variables outside of the string using the . to concatenate the item together.

As for the error you described above, it is more than likely when you do something like this... Auth::user()->member;

and member is defined like this...

// Laravel eloquent relationships
public function member() {
    return null;
}

Inside of a function like that you MUST return a $this->belongsTo or $this->hasA ...etc.

1 like
PacoW's avatar
Level 1

Thanks! I often do variables inside double quotes because it is more clear. I now realize there are exceptions that may not work.

Your suggestion doesn't solve the problem however. Perhaps the $name in the first function collides with the name() function because their names are equal. Or I overlooked something somewhere else in my code. Or the null messes things up...

It's 1:30 AM here, so some other day I'll continue my search... :-)

PacoW's avatar
Level 1

Unfortunately it doesn't. The problem might still be somewhere else in my code although I haven't found it yet, but I'll leave it for a few days.

I'll keep you updated.

The real frustration is, some error messages are clear, but others like these have 60 lines of stack trace but no clue. :)

Cronix's avatar
Cronix
Best Answer
Level 67

Where's the code where you're actually calling those methods?

I think the problem might be you need to make them attribute accessors. https://laravel.com/docs/5.4/eloquent-mutators#introduction

getNameAttribute() intead of name(), otherwise it thinks name() is a relationship (I believe). The same for nameOrUsername().

And you can put objects and arrays inside of a double quoted string. They just have to be surrounded by curly braces.

echo "This post belongs to {$user->name}";

echo "This post belongs to {$user['name']}";

1 like
PacoW's avatar
Level 1

I found it. Thanks all, your hints made me aware of some things I didn't think of:

  • Vendor code sometimes make assumptions about your code. In my case it assumed an attribute which my model doesn't have.
  • Functions inside a model can be regarded as relationships, even if they don't define one.
  • Accessors. I never thought of using them here, because the documentation only uses them to reformat existing attributes. As I see it now, they also allow you to introduce new "virtual" attributes, if I'm correct?

For those interested, and for those with similar problems, here is what went wrong...

The error message comes up when sending an e-mail:

  1. in HasAttributes.php line 403
  2. at Model->getRelationshipFromMethod('name') in HasAttributes.php line 386
  3. at Model->getRelationValue('name') in HasAttributes.php line 316
  4. at Model->getAttribute('name') in Model.php line 1305
  5. at Model->__isset('name') in Mailable.php line 443
  6. at Mailable->setAddress(object(User), null, 'to') in Mailable.php line 352
  7. at Mailable->to(object(User)) in PendingMail.php line 150

I should have shared this stacktrace in the first place. :-)

It's Mailable.php that expects an attribute called name from my User model which it doesn't have. My model has a first_name and a last_name (from Cartalyst/Sentinel) which are nullable, that's why I created the two functions in the first place: to be able to let Blade show a full name, or if (part of it) equals null to show the username as a fallback. I wasn't aware of Mailable expecting a name, but it seems to use it together with the user's e-mail address to compose the message: "To: name <email>".

To make things worse in my case, Laravel thinks it's a relationship because of my function which is by coincident called name() too, inside the User model. I wasn't aware of that neither, because I forgot it's just like for example calling $post->user() to retrieve a post's author model. I was thinking it is OK to place public functions inside a model, and perhaps it really is (correct me if I'm wrong), just as long as no other class expects an attribute or a relationship with the exact same name. So I agree I should make an accessor of it (or rename it to something like fullName). I made the accessor and the error was gone. Now some views have stopped working, but since I now know what's going on I should be able to make them work again.

To make things even worse... For some reason I began using other PHP versions and right after that the error appeared. I hadn't touched my code, so I was about to blame PHP. :-) Perhaps Laravel had cached a working version of my model class before I switched PHP versions.

Snapey's avatar

@gofish543

You cant access variables like that inside of the string. You must access the object variables outside of the string using the . to concatenate the item together.

Of course you can put variables inside double quoted strings. It is not necessary to use concatenation all the time.

Ideally use curly braces to delimit the variables;

    return "{$this->first_name} {$this->last_name}";

1 like

Please or to participate in this conversation.