laravel: function in model must return a relationship instance

I try to build a path for a model on laravel

I created a function in my model:

public function path()
{
return App\Helper\GeneralController::getURL($this);
}

with dd(App\Helper\GeneralController::getURL($this)) test I got the right answer. (output is a URL)

but in view with the call: $article->path I get this error:

App\Article:: path must return a relationship instance.

What is wrong?

71039 次浏览

You need to call it:

$article->path()

When you do $article->path, you're trying to use Eloquent relationship which you don't have.

path() is method not object element you need to call as method

$article->path();

You're calling a relationship.

$article->path

To call the method, use '()', like so,

$article->path()

I know this has already been answered and accepted. However, if the OP did want to use a property accessor rather than a method use the "get{property name}Attribute" syntax of Laravel to create a custom attribute.

Here is what it would look like for this specific case:

public function getPathAttribute()
{
return App\Helper\GeneralController::getURL($this);
}

using this approach "path" can now be called as an attribute and will not be resolved to a relationship using the syntax:

$article->path;

I faced that error when I forgot to write return before relation in the model!
check it out now!

Laravel 9 introduced a new way to define accessors/mutators within a model using Illuminate\Database\Eloquent\Casts\Attribute.

https://laravel.com/docs/9.x/eloquent-mutators#defining-an-accessor

public function path(): Attribute
{
return new Attribute(fn () => GeneralController::getURL($this));
}

For future visitors from Google, all the other answers can be applicable in certain scenarios, but you might want to also look if your method access modifier, if your method is protected and you try to call it you will be welcome with this error. You need change your method to public.