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

Laravel Lighthouse GraphQL基于模型自定义方法过滤报错如何解决

问题根因

你定义的isBatched是模型层的计算方法,不属于invoices数据库表的实际字段,而你在查询参数上使用的@eq指令是数据库层面的过滤指令,会直接在SQL中拼接where isBatched = ?的条件,因此触发字段不存在的报错。你原有schema中isBatched字段的@method定义是正常可用的,仅直接用它做查询过滤的逻辑有误。

解决方案

有两种可行实现方式,可按需选择:

方案1:SQL层面范围查询(推荐,性能好)

首先在Invoice模型中定义对应的查询范围,直接通过关联查询判断行数量:

// 在Invoice模型文件中新增方法
use Illuminate\Support\Facades\DB;

public function scopeWhereIsBatched($query, bool $isBatched)
{
    $condition = $isBatched ? '>' : '<=';
    return $query->has('rows', $condition, 1);
}

然后修改GraphQL schema中的查询定义,用@scope指令替换原有的@eq指令:

extend type Query {
    invoices: Invoice! @paginate @cache
    invoicesb(isBatched: Boolean @scope(name: "whereIsBatched")): [Invoice]! @paginate
}

该方案过滤逻辑直接在SQL层面执行,性能远高于后置过滤,适合绝大多数场景。

方案2:集合后置过滤(仅适合小数据量场景)

如果你的发票数据量级很小(千条以内),可以先查询全量数据再在集合层做过滤:
首先创建自定义查询解析器:

// App/GraphQL/Resolvers/InvoiceResolver.php
namespace App\GraphQL\Resolvers;

use App\Models\Invoice;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

class InvoiceResolver
{
    public function invoicesb(mixed $root, array $args): LengthAwarePaginator
    {
        $paginator = Invoice::paginate();
        return $paginator->setCollection(
            $paginator->getCollection()->filter(
                fn(Invoice $invoice) => $invoice->isBatched() === $args['isBatched']
            )
        );
    }
}

然后修改schema中的查询定义,绑定到自定义解析器:

extend type Query {
    invoices: Invoice! @paginate @cache
    invoicesb(isBatched: Boolean): [Invoice]! @paginate @resolver(method: "App\\GraphQL\\Resolvers\\InvoiceResolver@invoicesb")
}

该方案逻辑简单但需要先加载全量符合基础条件的记录,性能差,数据量较大时会严重拖慢查询速度。

内容的提问来源于stack exchange,提问作者Alireza Rahmani Khalili

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 03:15:03