首页 > 解决方案 > 渴望加载多态关系的相关模型

问题描述

在我的应用程序中,我有一堵墙。

每个帖子都可以有附件,比如VideoProduct(以及许多其他类型,因此为每种类型建立单独的关系将是一个坏主意)。

这是数据库结构示例:

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模型中,我定义了与附件的多态关系:

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仅在显示墙时加载照片?

非常感谢,并为我的英语不好感到抱歉。

标签: laraveleloquent

解决方案


如果您使用的是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();

推荐阅读