You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 8 多态关联如何单次查询正确加载对应类型关联模型

解决方案

步骤1:修正BookmarkItem模型关联定义

首先在BookmarkItem模型中新增统一的多态关联入口,替代拆分的posts/comments关联:

class BookmarkItem extends Model
{
    // 新增统一多态关联
    public function item()
    {
        return $this->morphTo('bookmark_item');
    }

    // 原有posts、comments关联可以保留不影响旧逻辑
    public function posts(): \Illuminate\Database\Eloquent\Relations\MorphToMany
    {
        return $this->morphedByMany(Post::class, 'bookmark_item');
    }

    public function comments(): \Illuminate\Database\Eloquent\Relations\MorphToMany
    {
        return $this->morphedByMany(Comment::class, 'bookmark_item');
    }
}

步骤2:使用多态关联按需预加载实现单次查询

Laravel原生支持对morphTo类型关联的按类型预加载,查询代码如下:

use Illuminate\Database\Eloquent\Relations\MorphTo;

$result = $bookmark->items()
    ->with([
        'item' => function (MorphTo $morphTo) {
            // 按关联类型加载对应模型
            $morphTo->morphWith([
                Post::class => [], // 可在数组中添加Post需要额外预加载的关联
                Comment::class => [], // 可在数组中添加Comment需要额外预加载的关联
            ]);
        }
    ])
    // 此处可统一添加筛选、排序逻辑,例:
    // ->whereDate('created_at', '>=', '2024-01-01')
    // ->orderBy('created_at', 'desc')
    ->get()
    // 可选:调整返回结构,匹配原有的posts/comments字段格式
    ->map(function ($bookmarkItem) {
        $itemData = $bookmarkItem->toArray();
        // 按类型把关联数据放到对应键下,移除统一的item字段
        if ($bookmarkItem->bookmark_item_type === \App\Models\Post::class) {
            $itemData['posts'] = $itemData['item'];
        } elseif ($bookmarkItem->bookmark_item_type === \App\Models\Comment::class) {
            $itemData['comments'] = $itemData['item'];
        }
        unset($itemData['item']);
        return $itemData;
    })
    ->toArray();

方案说明

  • 该方案仅执行4次查询:1次查询bookmark_items表、1次批量查询匹配的Post数据、1次批量查询匹配的Comment数据,性能与拆分两次查询的方案基本一致
  • 所有筛选、排序逻辑只需要编写一次,不需要拆分两次查询实现
  • 不会出现多余关联加载的问题,每个书签条目只会加载对应类型的关联数据

内容的提问来源于stack exchange,提问作者HashtagForgotName

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 21:06:01