渴望加载多晶关系的相关模型

时间:2019-11-10 19:42:50

标签: laravel eloquent

在我的应用中,我有一堵墙,上面贴满了帖子。

每个帖子都可以包含附件,例如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张照片?

在此先感谢您,我的英语不好。

1 个答案:

答案 0 :(得分:0)

如果您使用的是 Laravel 5.8.22或更高版本,则可以使用 嵌套急切加载morphTo关系 。`

请参见docuemntation

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();