Каков вариант использования первого аргумента метода morphTo?

Согласно этой проблеме, при использовании имени пользовательского метода для определения полиморфной связи в Laravel аргумент имениmorphTo метод работает не так, как ожидалось. Предположим, что простая структура полиморфной таблицы:

posts
    id - integer
    name - string

users
    id - integer
    name - string

images
    id - integer
    url - string
    imageable_id - integer
    imageable_type - string

и эта структура модели:

<?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');
    }
}

При загрузке этих отношений:

$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

Итак, вопросы: каков вариант использования аргумента имени morphToметод? и Как правильно настроить имя отношения, как в примере выше?

2 ответа

Решение

В документацию Laravel7.x добавлено объяснение:

Если вам нужно указать индивидуальный type а также id столбцы для morphTo отношение, всегда убедитесь, что вы передаете имя отношения (которое должно точно соответствовать имени метода) в качестве первого параметра:

/**
 * Get the model that the image belongs to.
 */
public function picturable()
{
    return $this->morphTo(__FUNCTION__, 'imageable_type', 'imageable_id');
}

Я думаю nameПараметр позволяет настроить имя свойства, в котором будет храниться соответствующая модель. Итак, в контроллере вы должны указать имена, которые вы ожидаете иметь в качестве отношений:

    public function picturable1()
    {
        return $this->morphTo('picturable1', 'imageable_type', 'imageable_id');
        // or return $this->morphTo(null, 'imageable_type', 'imageable_id');
    }

    public function picturable2()
    {
        return $this->morphTo('picturable2', 'imageable_type', 'imageable_id');
        // or return $this->morphTo(null, 'imageable_type', 'imageable_id');
    }
Другие вопросы по тегам