在 Laravel 9 中,在异步队列中复用 Spatie\QueryBuilder\QueryBuilder 来生成查询 SQL
1、在 Laravel 9 中,现在已经实现一个列表的 API,其基于 Spatie\QueryBuilder\QueryBuilder 实现从 API 请求轻松构建 Eloquent 查询。但是,现在需要在列表页面实现一个导出 Excel 的功能,计划在异步队列中实现。那么,要想复用之前的构建 Eloquent 查询的代码,好像只能够将 Request 对象传递至队列中?
2、提示报错:Serialization of ‘Closure’ is not allowed。如图1
{
"status_code": 500,
"code": 0,
"message": "Serialization of 'Closure' is not allowed",
"trace": {
"line": 158,
"file": "E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\Queue.php",
"class": "Exception",
"trace": [
"#0 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\Queue.php(158): serialize(Object(Modules\\Order\\Jobs\\OrderShippingLogExportJob))",
"#1 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\Queue.php(127): Illuminate\\Queue\\Queue->createObjectPayload(Object(Modules\\Order\\Jobs\\OrderShippingLogExportJob), 'queues:export_q...')",
"#2 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\RedisQueue.php(212): Illuminate\\Queue\\Queue->createPayloadArray(Object(Modules\\Order\\Jobs\\OrderShippingLogExportJob), 'queues:export_q...', '')",
"#3 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\Queue.php(105): Illuminate\\Queue\\RedisQueue->createPayloadArray(Object(Modules\\Order\\Jobs\\OrderShippingLogExportJob), 'queues:export_q...', '')",
"#4 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\RedisQueue.php(136): Illuminate\\Queue\\Queue->createPayload(Object(Modules\\Order\\Jobs\\OrderShippingLogExportJob), 'queues:export_q...', '')",
"#5 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Queue\\Queue.php(57): Illuminate\\Queue\\RedisQueue->push(Object(Modules\\Order\\Jobs\\OrderShippingLogExportJob), '', 'export_queue')",
"#6 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Bus\\Dispatcher.php(246): Illuminate\\Queue\\Queue->pushOn('export_queue', Object(Modules\\Order\\Jobs\\OrderShippingLogExportJob))",
"#7 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Bus\\Dispatcher.php(229): Illuminate\\Bus\\Dispatcher->pushCommandToQueue(Object(Illuminate\\Queue\\RedisQueue), Object(Modules\\Order\\Jobs\\OrderShippingLogExportJob))",
"#8 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Bus\\Dispatcher.php(77): Illuminate\\Bus\\Dispatcher->dispatchToQueue(Object(Modules\\Order\\Jobs\\OrderShippingLogExportJob))",
"#9 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Bus\\PendingDispatch.php(193): Illuminate\\Bus\\Dispatcher->dispatch(Object(Modules\\Order\\Jobs\\OrderShippingLogExportJob))",
"#10 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Bus\\Dispatchable.php(18): Illuminate\\Foundation\\Bus\\PendingDispatch->__destruct()",
"#11 E:\\wwwroot\\object\\Modules\\Order\\Services\\OrderShippingLogService.php(205): Modules\\Order\\Jobs\\OrderShippingLogExportJob::dispatch(Object(App\\Models\\JobStatus), Array, Object(Illuminate\\Http\\Request))",
"#12 E:\\wwwroot\\object\\Modules\\Order\\Http\\Controllers\\Api\\OrderShippingLogController.php(46): Modules\\Order\\Services\\OrderShippingLogService->export(Array, Object(Illuminate\\Http\\Request))",
"#13 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Controller.php(54): Modules\\Order\\Http\\Controllers\\Api\\OrderShippingLogController->export()",
"#14 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\ControllerDispatcher.php(43): Illuminate\\Routing\\Controller->callAction('export', Array)",
"#15 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php(259): Illuminate\\Routing\\ControllerDispatcher->dispatch(Object(Illuminate\\Routing\\Route), Object(Modules\\Order\\Http\\Controllers\\Api\\OrderShippingLogController), 'export')",
"#16 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php(204): Illuminate\\Routing\\Route->runController()",
"#17 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(725): Illuminate\\Routing\\Route->run()",
"#18 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(141): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))",
"#19 E:\\wwwroot\\object\\vendor\\spatie\\laravel-permission\\src\\Middlewares\\RoleOrPermissionMiddleware.php(26): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#20 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(180): Spatie\\Permission\\Middlewares\\RoleOrPermissionMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure), 'order_transport...')",
"#21 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Middleware\\SubstituteBindings.php(50): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#22 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(180): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#23 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Auth\\Middleware\\Authenticate.php(44): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#24 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(180): Illuminate\\Auth\\Middleware\\Authenticate->handle(Object(Illuminate\\Http\\Request), Object(Closure), 'api')",
"#25 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(116): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#26 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(726): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))",
"#27 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(703): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(Illuminate\\Http\\Request))",
"#28 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(667): Illuminate\\Routing\\Router->runRoute(Object(Illuminate\\Http\\Request), Object(Illuminate\\Routing\\Route))",
"#29 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(656): Illuminate\\Routing\\Router->dispatchToRoute(Object(Illuminate\\Http\\Request))",
"#30 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(190): Illuminate\\Routing\\Router->dispatch(Object(Illuminate\\Http\\Request))",
"#31 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(141): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}(Object(Illuminate\\Http\\Request))",
"#32 E:\\wwwroot\\object\\app\\Http\\Middleware\\QueryListenerMiddleware.php(30): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#33 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(180): App\\Http\\Middleware\\QueryListenerMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#34 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#35 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#36 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#37 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#38 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#39 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance.php(86): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#40 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(180): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#41 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Http\\Middleware\\HandleCors.php(62): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#42 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(180): Illuminate\\Http\\Middleware\\HandleCors->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#43 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Http\\Middleware\\TrustProxies.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#44 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(180): Illuminate\\Http\\Middleware\\TrustProxies->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#45 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(116): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#46 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(165): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))",
"#47 E:\\wwwroot\\object\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(134): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request))",
"#48 E:\\wwwroot\\object\\public\\index.php(52): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request))",
"#49 {main}"
]
}
}
3、尝试先将请求对象转换为数组,然后在异步队列中,再重新转换为请求对象。尝试打印 原生的请求对象 与 转换后的请求对象 的所有请求数据。完全相等,符合预期。
$params = $this->request->all(); print_r($params); $request = new Request($params); print_r($request); print_r($request->all()); exit;
Array
(
[filter] => Array
(
[shop_plat_id] => Array
(
[0] => 1
[1] => 2
)
[shop_id] => Array
(
[0] => 1
[1] => 14
)
[logistic_channel_id] => Array
(
[0] => 304872
[1] => 474241
)
[logistic_company_id] => Array
(
[0] => 10336
[1] => 10340
)
[operated_source] => Array
(
[0] => 1
[1] => 2
)
[plat_order_no] => Array
(
[0] => GM20240202055938
[1] => GM20240131081251
)
[logistic_freight_no] => Array
(
[0] => PH900016739XX
[1] => PH900890788XX
)
[logistic_freight_transfer_no] => Array
(
[0] => PH900016739XX
[1] => PH900890788XX
)
[logistic_freight_inner_no] => Array
(
[0] => PH900016739XX
[1] => PH900890788XX
)
[logistic_virtual_number] => Array
(
[0] => GM20240202055938766
[1] => GM20240131081251410
)
[shipping_type] => Array
(
[0] => 1
[1] => 2
)
[shipping_status] => Array
(
[0] => 2
[1] => 3
)
[shipping_at_gmt_start] => 2024-02-02 05:52:31
[shipping_at_gmt_end] => 2024-02-04 05:52:31
[operated_at_gmt_start] => 2024-02-02 05:52:31
[operated_at_gmt_end] => 2024-02-04 05:52:31
)
[per_page] => 20
[page] => 1
)
Illuminate\Http\Request Object
(
[attributes] => Symfony\Component\HttpFoundation\ParameterBag Object
(
[parameters:protected] => Array
(
)
)
[request] => Symfony\Component\HttpFoundation\InputBag Object
(
[parameters:protected] => Array
(
)
)
[query] => Symfony\Component\HttpFoundation\InputBag Object
(
[parameters:protected] => Array
(
[filter] => Array
(
[shop_plat_id] => Array
(
[0] => 1
[1] => 2
)
[shop_id] => Array
(
[0] => 1
[1] => 14
)
[logistic_channel_id] => Array
(
[0] => 304872
[1] => 474241
)
[logistic_company_id] => Array
(
[0] => 10336
[1] => 10340
)
[operated_source] => Array
(
[0] => 1
[1] => 2
)
[plat_order_no] => Array
(
[0] => GM20240202055938
[1] => GM20240131081251
)
[logistic_freight_no] => Array
(
[0] => PH900016739XX
[1] => PH900890788XX
)
[logistic_freight_transfer_no] => Array
(
[0] => PH900016739XX
[1] => PH900890788XX
)
[logistic_freight_inner_no] => Array
(
[0] => PH900016739XX
[1] => PH900890788XX
)
[logistic_virtual_number] => Array
(
[0] => GM20240202055938766
[1] => GM20240131081251410
)
[shipping_type] => Array
(
[0] => 1
[1] => 2
)
[shipping_status] => Array
(
[0] => 2
[1] => 3
)
[shipping_at_gmt_start] => 2024-02-02 05:52:31
[shipping_at_gmt_end] => 2024-02-04 05:52:31
[operated_at_gmt_start] => 2024-02-02 05:52:31
[operated_at_gmt_end] => 2024-02-04 05:52:31
)
[per_page] => 20
[page] => 1
)
)
[server] => Symfony\Component\HttpFoundation\ServerBag Object
(
[parameters:protected] => Array
(
)
)
[files] => Symfony\Component\HttpFoundation\FileBag Object
(
[parameters:protected] => Array
(
)
)
[cookies] => Symfony\Component\HttpFoundation\InputBag Object
(
[parameters:protected] => Array
(
)
)
[headers] => Symfony\Component\HttpFoundation\HeaderBag Object
(
[headers:protected] => Array
(
)
[cacheControl:protected] => Array
(
)
)
[content:protected] =>
[languages:protected] =>
[charsets:protected] =>
[encodings:protected] =>
[acceptableContentTypes:protected] =>
[pathInfo:protected] =>
[requestUri:protected] =>
[baseUrl:protected] =>
[basePath:protected] =>
[method:protected] =>
[format:protected] =>
[session:protected] =>
[locale:protected] =>
[defaultLocale:protected] => en
[preferredFormat:Symfony\Component\HttpFoundation\Request:private] =>
[isHostValid:Symfony\Component\HttpFoundation\Request:private] => 1
[isForwardedValid:Symfony\Component\HttpFoundation\Request:private] => 1
[json:protected] =>
[convertedFiles:protected] =>
[userResolver:protected] =>
[routeResolver:protected] =>
)
Array
(
[filter] => Array
(
[shop_plat_id] => Array
(
[0] => 1
[1] => 2
)
[shop_id] => Array
(
[0] => 1
[1] => 14
)
[logistic_channel_id] => Array
(
[0] => 304872
[1] => 474241
)
[logistic_company_id] => Array
(
[0] => 10336
[1] => 10340
)
[operated_source] => Array
(
[0] => 1
[1] => 2
)
[plat_order_no] => Array
(
[0] => GM20240202055938
[1] => GM20240131081251
)
[logistic_freight_no] => Array
(
[0] => PH900016739XX
[1] => PH900890788XX
)
[logistic_freight_transfer_no] => Array
(
[0] => PH900016739XX
[1] => PH900890788XX
)
[logistic_freight_inner_no] => Array
(
[0] => PH900016739XX
[1] => PH900890788XX
)
[logistic_virtual_number] => Array
(
[0] => GM20240202055938766
[1] => GM20240131081251410
)
[shipping_type] => Array
(
[0] => 1
[1] => 2
)
[shipping_status] => Array
(
[0] => 2
[1] => 3
)
[shipping_at_gmt_start] => 2024-02-02 05:52:31
[shipping_at_gmt_end] => 2024-02-04 05:52:31
[operated_at_gmt_start] => 2024-02-02 05:52:31
[operated_at_gmt_end] => 2024-02-04 05:52:31
)
[per_page] => 20
[page] => 1
)
4、最终实现如下,符合预期。如图2
$orderShippingLogQueryBuilder = $this->repository->QueryBuilder($params);
$orderShippingLogQueryBuilder->chunk(100, function ($orderShippingLogs) {
foreach ($orderShippingLogs as $orderShippingLog) {
echo $orderShippingLog->id;
}
});
exit;
/**
* 查询生成器
* @param array $criteria
* @return QueryBuilder
*/
public function QueryBuilder(array $criteria): QueryBuilder
{
return QueryBuilder::for(OrderShippingLog::class, new Request($criteria))
->allowedFilters([
AllowedFilter::exact('shop_plat_id'),
AllowedFilter::exact('shop_id'),
AllowedFilter::exact('logistic_channel_id'),
AllowedFilter::exact('logistic_company_id'),
AllowedFilter::exact('operated_source'),
AllowedFilter::exact('plat_order_no'),
AllowedFilter::exact('logistic_freight_no'),
AllowedFilter::exact('logistic_freight_transfer_no'),
AllowedFilter::exact('logistic_freight_inner_no'),
AllowedFilter::exact('logistic_virtual_number'),
AllowedFilter::exact('shipping_type'),
AllowedFilter::exact('shipping_status'),
AllowedFilter::scope('shipping_at_gmt_start'),
AllowedFilter::scope('shipping_at_gmt_end'),
AllowedFilter::scope('operated_at_gmt_start'),
AllowedFilter::scope('operated_at_gmt_end'),
])
->with('shopPlat:id,title')
->with('shop:id,title')
->with('order.orderItemLogisticsFeatures')
->with('order.urgentType:id,title,color')
->with('logisticChannel:id,title')
->with('operatorUser:id,name,number')
->defaultSort('-id');
}


1 条回复
[…] 1、参考:在 Laravel 9 中,在异步队列中复用 SpatieQueryBuilderQueryBuilder 来生成查询 SQL […]