在 Laravel 9 中,基于 spatie/laravel-query-builder 查询关联表中的字段时,按需添加 join 语句的实现
1、现阶段的实现如下,最终生成的 SQL 永远都需要 join 关联上其他几张表,否则会报错
{ "filter": { "sku_code": [ "smileying01" ] }, "per_page": 100, "page": 1 }
// 单个模糊检索,多个精确检索:订单号、交易号、退货单号、退货快递单号、货运单号、商品SKU // 键为请求参数,值为 SQL 查询字段 $fields = [ 'plat_order_no' => 'plat_order_no', 'transaction_no' => 'transaction_no', 'return_order_no' => 'return_order_no', 'return_logistics_freight_no' => 'return_order_logistics.logistics_freight_no', 'logistics_freight_no' => 'logistics_freight_no', 'sku_code' => 'return_order_items.sku_code', ]; $allowedFilters = [ AllowedFilter::exact('signing_status'), AllowedFilter::partial('remark'), AllowedFilter::exact('return_type'), AllowedFilter::exact('processing_method'), AllowedFilter::scope('created_at_gmt_start'), AllowedFilter::scope('created_at_gmt_end'), AllowedFilter::scope('order_payment_at_gmt_start'), AllowedFilter::scope('order_payment_at_gmt_end'), AllowedFilter::scope('order_delivery_at_gmt_start'), AllowedFilter::scope('order_delivery_at_gmt_end'), ]; foreach ($fields as $key => $field) { if (isset($criteria['filter'][$key])) { if (count($criteria['filter'][$key]) > 1) { // 多个精确检索 $allowedFilters[] = AllowedFilter::exact($field); } else { // 单个模糊检索 $allowedFilters[] = AllowedFilter::partial($field); } if ($key != $field) { $criteria['filter'][$field] = $criteria['filter'][$key]; unset($criteria['filter'][$key]); } } } // 退货原因ID,转换 SQL 查询字段 if (isset($criteria['filter']['refund_reason_id'])) { $criteria['filter']['return_order_refund_reasons.refund_reason_id'] = $criteria['filter']['refund_reason_id']; unset($criteria['filter']['refund_reason_id']); $allowedFilters[] = AllowedFilter::exact('return_order_refund_reasons.refund_reason_id'); } $builder = QueryBuilder::for(ReturnOrder::class, new Request($criteria)) ->select('return_orders.*') ->leftJoin('return_order_items', 'return_order_items.return_order_id', 'return_orders.id') ->leftJoin('return_order_refund_reasons', 'return_order_refund_reasons.return_order_id', 'return_orders.id') ->leftJoin('return_order_logistics', 'return_order_logistics.return_order_id', 'return_orders.id') ->allowedFilters($allowedFilters) ->with('returnOrderItems') ->with('returnOrderRefundReasons.refundReason') ->with('returnOrderLogistics') ->with('resendOrder') ->with('order.orderItemLogisticsFeatures') ->defaultSort('-id');
select count(*) as aggregate from `return_orders` left join `return_order_items` on `return_order_items`.`return_order_id` = `return_orders`.`id` left join `return_order_refund_reasons` on `return_order_refund_reasons`.`return_order_id` = `return_orders`.`id` left join `return_order_logistics` on `return_order_logistics`.`return_order_id` = `return_orders`.`id` where ( LOWER(`return_order_items`.`sku_code`) LIKE '%smileying01%' )
2、调整后的实现如下,在准备好 new Request($criteria) 之后,再判断是否 join ,生成的 SQL 按需关联其他表,符合预期。如图1
// 单个模糊检索,多个精确检索:订单号、交易号、退货单号、退货快递单号、货运单号、商品SKU // 键为请求参数,值为 SQL 查询字段 $fields = [ 'plat_order_no' => 'plat_order_no', 'transaction_no' => 'transaction_no', 'return_order_no' => 'return_order_no', 'return_logistics_freight_no' => 'return_order_logistics.logistics_freight_no', 'logistics_freight_no' => 'logistics_freight_no', 'sku_code' => 'return_order_items.sku_code', ]; $allowedFilters = [ AllowedFilter::exact('signing_status'), AllowedFilter::partial('remark'), AllowedFilter::exact('return_type'), AllowedFilter::exact('processing_method'), AllowedFilter::scope('created_at_gmt_start'), AllowedFilter::scope('created_at_gmt_end'), AllowedFilter::scope('order_payment_at_gmt_start'), AllowedFilter::scope('order_payment_at_gmt_end'), AllowedFilter::scope('order_delivery_at_gmt_start'), AllowedFilter::scope('order_delivery_at_gmt_end'), ]; foreach ($fields as $key => $field) { if (isset($criteria['filter'][$key])) { if (count($criteria['filter'][$key]) > 1) { // 多个精确检索 $allowedFilters[] = AllowedFilter::exact($field); } else { // 单个模糊检索 $allowedFilters[] = AllowedFilter::partial($field); } if ($key != $field) { $criteria['filter'][$field] = $criteria['filter'][$key]; unset($criteria['filter'][$key]); } } } // 退货原因ID,转换 SQL 查询字段 if (isset($criteria['filter']['refund_reason_id'])) { $criteria['filter']['return_order_refund_reasons.refund_reason_id'] = $criteria['filter']['refund_reason_id']; unset($criteria['filter']['refund_reason_id']); $allowedFilters[] = AllowedFilter::exact('return_order_refund_reasons.refund_reason_id'); } $builder = QueryBuilder::for(ReturnOrder::class, new Request($criteria))->select('return_orders.*'); // 退货快递单号 if (isset($criteria['filter']['return_logistics_freight_no'])) { $builder->leftJoin('return_order_logistics', 'return_order_logistics.return_order_id', 'return_orders.id'); } // 商品 SKU 编码 if (isset($criteria['filter']['return_order_items.sku_code'])) { $builder->leftJoin('return_order_items', 'return_order_items.return_order_id', 'return_orders.id'); } // 退货原因ID if (isset($criteria['filter']['refund_reason_id'])) { $builder->leftJoin('return_order_refund_reasons', 'return_order_refund_reasons.return_order_id', 'return_orders.id'); $allowedFilters[] = AllowedFilter::exact('return_order_refund_reasons.refund_reason_id'); } $builder->allowedFilters($allowedFilters) ->with('returnOrderItems') ->with('returnOrderRefundReasons.refundReason') ->with('returnOrderLogistics') ->with('resendOrder') ->with('order.orderItemLogisticsFeatures') ->defaultSort('-id');
select count(*) as aggregate from `return_orders` left join `return_order_items` on `return_order_items`.`return_order_id` = `return_orders`.`id` where ( LOWER(`return_order_items`.`sku_code`) LIKE '%smileying01%' )
近期评论