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

Laravel中如何基于共享标签为每个Place查询关联Books?

解决方案:为Place获取共享标签的Books

你的场景是两个独立的多对多关联(Books ↔ Tags、Places ↔ Tags),而非多态关联,所以不用纠结多态的方案,直接通过关联查询就能实现需求。下面分MySQL原生语句和Laravel Eloquent两种方式说明:

一、MySQL原生查询

方式1:子查询+IN语句

先获取目标Place关联的所有Tag ID,再筛选关联这些Tag的Books,最后去重(避免同一Book因多个共享Tag重复出现):

SELECT DISTINCT b.*
FROM books b
JOIN book_tags bt ON b.id = bt.book_id
WHERE bt.tag_id IN (
    SELECT pt.tag_id
    FROM place_tags pt
    WHERE pt.place_id = 1 -- 替换成你的目标Place ID
);

方式2:多表JOIN(性能更优)

直接通过Tag ID关联三张表,同样去重:

SELECT DISTINCT b.*
FROM books b
JOIN book_tags bt ON b.id = bt.book_id
JOIN place_tags pt ON bt.tag_id = pt.tag_id
WHERE pt.place_id = 1; -- 替换成你的目标Place ID

二、Laravel Eloquent实现

假设你已经在模型中定义了多对多关联:

  • Book模型:public function tags() { return $this->belongsToMany(Tag::class); }
  • Place模型:public function tags() { return $this->belongsToMany(Tag::class); }

方式1:基于已加载的Place Tags

先获取目标Place,再通过whereHas筛选关联共享Tag的Books:

$placeId = 1; // 目标Place ID
$place = Place::find($placeId);

$relatedBooks = Book::whereHas('tags', function ($query) use ($place) {
    $query->whereIn('tags.id', $place->tags->pluck('id'));
})->distinct()->get();

方式2:子查询关联(更高效,避免提前加载Tags)

直接在查询中关联place_tags表,减少一次数据库查询:

use Illuminate\Support\Facades\DB;

$placeId = 1;
$relatedBooks = Book::whereHas('tags', function ($query) use ($placeId) {
    $query->whereExists(function ($subQuery) use ($placeId) {
        $subQuery->select(DB::raw(1))
            ->from('place_tags')
            ->whereColumn('place_tags.tag_id', 'tags.id')
            ->where('place_tags.place_id', $placeId);
    });
})->distinct()->get();

两种方式都能帮你精准获取到和指定Place拥有共同标签的所有Books,根据你的实际场景选择即可~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:58:22