Жесткая загрузка полиморфных отношений, связанных с моделью - PullRequest
0 голосов
/ 10 ноября 2019

В моем приложении есть стена с сообщениями.

Каждое сообщение может иметь вложения, такие как Video или Product (и многие другие типы, поэтому создание отдельных отношений для каждого типа будет плохимидея).

Вот пример структуры базы данных:

videos
    id
    ...

products
    id
    ...

product_photos
    product_id
    ...

posts
    id
    ...

post_attachments
    post_id
    attachment_id
    attachment_type

В Post модели я определил отношение к PostAttachment:

class Post extends Model
{
    public function attachments()
    {
        $this->hasMany(PostAttachment::class);
    }
}

В PostAttachmentМодель I определила полиморфное отношение к вложению:

class PostAttachment extends Model
{
    public function attachment()
    {
        return $this->morphTo();
    }
}

Если я хочу получить всю стену, я могу сделать что-то вроде этого:

$posts = Post::with([
    'attachments',
    'attachments.attachment'
])->get();

, что приведет к:

[
    {
        "id": 1,
        ...
        "attachments": [
            {
                ...
                "attachment_type": "App\Models\Video",
                "attachment": {
                    "id": 101,
                    ...
                }
            },
            {
                ...
                "attachment_type": "App\Models\Product",
                "attachment": {
                    "id": 203,
                    ...
                }
            },

        ]
    }
]

Но что, если я хочу добавить Product фотографий в результат? Я не могу сделать что-то подобное:

$posts = Post::with([
    'attachments',
    'attachments.attachment',
    'attachments.attachment.photos'
])->get();

, потому что отношение photos существует только в модели Product, а не в Video.

Грязное решение - включить отношениезагрузка в определении модели:

class Product
{
    protected $with = [
        'photos'
    ];

    ...
}

Но с этим решением фотографии будут возвращены, даже если я получу Product модель напрямую.

Как я могу загрузить Product фотографии только при показеwall?

Большое спасибо заранее, и извините за мой плохой английский.

1 Ответ

0 голосов
/ 11 ноября 2019

Если вы используете Laravel 5.8.22 или выше , вы можете использовать Вложенная готовая загрузка отношений morphTo .`

См. документация

use Illuminate\Database\Eloquent\Relations\MorphTo;


$posts = Post::query;

$posts = $posts->with([
    'attachments.attachment' => function (MorphTo $morphTo) {
                $morphTo->morphWith([
                    Product::class => ['photos'],
                    //add more if any
                ]);
            }]);

$posts = $posts->get();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...