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

如何在Filament的ComponentRelationManager中筛选Type为Null的多态多对多关联

解决Filament关联管理器中Attach动作的可选记录筛选问题

问题分析

你定义的components关联自带wherePivot('type', 'component')约束,Filament的ComponentRelationManager默认会基于这个关联的查询生成Attach动作的可选记录列表。当你在recordSelectOptionsQuery中添加where('product_morph.type', null)时,两个条件会以AND叠加,导致查询逻辑变为找type同时等于component和null的记录,自然无法得到想要的未关联产品。

解决方案

有两种可行的实现方式,任选其一即可:

方式1:移除关联自带的约束后添加新条件

在你的ComponentRelationManager类中重写getRecordSelectOptionsQuery方法,先清除关联自带的wherePivot约束,再添加筛选未关联产品的条件:

use Illuminate\Database\Eloquent\Builder;

protected function getRecordSelectOptionsQuery(): Builder
{
    $query = parent::getRecordSelectOptionsQuery();

    // 过滤掉关联定义中添加的type=component的约束
    $query->getQuery()->wheres = collect($query->getQuery()->wheres)->filter(function ($where) {
        return !($where['type'] === 'Basic' 
            && $where['column'] === 'product_morph.type' 
            && $where['operator'] === '=' 
            && $where['value'] === 'component');
    })->values()->all();

    // 筛选未被关联(type为null)且不是当前产品本身的记录
    return $query
        ->whereNull('product_morph.type')
        ->where('products.id', '!=', $this->getOwnerRecord()->id);
}

方式2:直接构建独立查询(更稳定)

绕开关联的默认查询,直接通过左连接product_morph表来筛选未被当前产品关联的记录:

use Illuminate\Database\Eloquent\Builder;

protected function getRecordSelectOptionsQuery(): Builder
{
    $currentProductId = $this->getOwnerRecord()->id;

    return \App\Models\Product::query()
        ->leftJoin('product_morph', function ($join) use ($currentProductId) {
            $join->on('product_morph.model_id', '=', 'products.id')
                 ->where('product_morph.model_type', \App\Models\Product::class)
                 ->where('product_morph.related_id', '=', $currentProductId)
                 ->where('product_morph.related_type', \App\Models\Product::class);
        })
        ->whereNull('product_morph.type')
        ->where('products.id', '!=', $currentProductId);
}

说明

  • 两种方法都加入了where('products.id', '!=', $currentProductId),避免自引用关联中把产品关联给自己。
  • 方式2的查询逻辑更直观,也不用担心Laravel查询构造器的wheres结构变化导致过滤失效,推荐使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 02:27:09