According to this issue, when using custom method name to define a polymorphic relationship on Laravel, the name argument of the morphTo
method doesn't work as expected, Let's assume a simple polymorphic table structure:
posts
id - integer
name - string
users
id - integer
name - string
images
id - integer
url - string
imageable_id - integer
imageable_type - string
and this model structure:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Image extends Model
{
// ...
// It doesn't work as expected
public function picturable1()
{
return $this->morphTo('imageable');
}
// It doesn't work as expected
public function picturable2()
{
return $this->morphTo('imageable', 'imageable_type', 'imageable_id');
}
// It works unexpectedly
public function picturable3()
{
return $this->morphTo(null, 'imageable_type', 'imageable_id');
}
}
When loading these relationships:
$image = \App\Image::with('picturable1')->find(1);
$image->picturable1; // exists and returns null but imageable instance was expected
$image->imageable; // returns imageable instance unexpectedly
$image = \App\Image::with('picturable2')->find(1);
$image->picturable2; // exists and returns null but imageable instance was expected
$image->imageable; // returns imageable instance unexpectedly
$image = \App\Image::with('picturable3')->find(1);
$image->picturable3; // returns imageable instance as expected
$image->imageable; // doesn't exists as expected
So the questions are, What is the use case of the name argument of the morphTo
method?
and What is the right way to customize the name of the relationship like above example?
An explanation is added to Laravel 7.x documentation:
If you need to specify custom
type
andid
columns for themorphTo
relation, always ensure you pass the relationship name (which should exactly match the method name) as the first parameter:
/**
* Get the model that the image belongs to.
*/
public function picturable()
{
return $this->morphTo(__FUNCTION__, 'imageable_type', 'imageable_id');
}