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

Laravel 5.1:带WHERE条件的多态关联查询问题

解决多态关联中筛选关联对象字段的问题

嘿,我看你在处理多态关联的查询时遇到了麻烦,就是要根据关联对象的字段来筛选结果对吧?结合你给的示例数据,我来给你梳理几种常见场景的解决办法,都是Laravel里常用的操作:

场景1:查询关联特定类型对象且满足字段条件的Content

比如你想找所有关联MusicTrack且page_id = 1的Content记录(就是你示例里那条content_id=555的),直接用Laravel专门为多态关联做的whereHasMorph方法就行,代码是这样的:

use App\Content;
use App\MusicTrack;

$contents = Content::whereHasMorph('contentable', [MusicTrack::class], function ($query) {
    $query->where('page_id', 1);
})->get();

如果需要同时筛选多种类型的对象,比如同时找关联MusicTrack和Image且page_id=1的Content,只需要把类型数组扩大:

use App\Image;

$contents = Content::whereHasMorph('contentable', [MusicTrack::class, Image::class], function ($query) {
    $query->where('page_id', 1);
})->get();

场景2:查询拥有符合条件的多态关联对象的Page

如果你想反过来,找所有拥有关联MusicTrack(且MusicTrack满足某个条件)的Page,那可以通过嵌套的whereHas来实现,前提是你的Page模型已经定义了和MusicTrack的关联:

首先在Page模型里加关联:

class Page extends Model
{
    public function musicTracks()
    {
        return $this->hasMany(MusicTrack::class);
    }

    public function videos()
    {
        return $this->hasMany(Video::class);
    }

    public function images()
    {
        return $this->hasMany(Image::class);
    }
}

然后就可以这样查询:

$pages = Page::whereHas('musicTracks.content', function ($query) {
    // 这里可以筛选关联的MusicTrack字段,比如找id=10的MusicTrack对应的Page
    $query->whereHasMorph('contentable', MusicTrack::class, function ($q) {
        $q->where('id', 10);
    });
})->get();

场景3:跨所有多态类型筛选通用字段

如果你的MusicTrack、Video、Image都有同一个字段(比如page_id),你想筛选所有关联对象的该字段等于某个值的Content,可以直接用*匹配所有多态类型:

$contents = Content::whereHasMorph('contentable', '*', function ($query) {
    $query->where('page_id', 1);
})->get();

这样不管关联的是音乐、视频还是图片,只要对应模型的page_id是1,都会被筛选出来。

旧版本Laravel的兼容方案

如果你的Laravel版本低于5.8,whereHasMorph还没出,那可以用原生SQL的方式来实现,比如筛选关联MusicTrack且page_id=1的Content:

use Illuminate\Support\Facades\DB;

$contents = Content::where(function ($query) {
    $query->where('contentable_type', MusicTrack::class)
          ->whereExists(function ($q) {
              $q->select(DB::raw(1))
                ->from('music_tracks')
                ->whereColumn('music_tracks.id', 'contents.contentable_id')
                ->where('music_tracks.page_id', 1);
          });
})->get();

这样应该就能解决你在多态关联查询中筛选关联对象字段的问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:11:52