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
相关产品推荐
相关产品推荐

