Laravel队列的实现
一、 修改根目录 .env 文件的QUEUE_CONNECTION字段配置 为database或sync,这俩我使用sync
Laravel可配置多种队列驱动,包括 "sync", "database", "beanstalkd", "sqs", "redis", "null"(具体参见app/config/queue.php) 其中sync为同步,database为使用数据库,后面三种为第三方队列服务,最后一种为不使用队列。 通过在 .env 中的 QUEUE_CONNECTION 选项,来决定选择何种驱动。 如 QUEUE_CONNECTION=database 即为选择数据库驱动队列。
二、创建一个数据表存放队列
php artisan queue:table
php artisan migrate
三、生成任务类 队列的任务类都默认放在 app/Jobs 目录下。
如果这个目录不存在,当运行 make:job Artisan 命令时目录就会被自动创建。
可以用以下的 Artisan 命令来生成一个新的队列任务:
php artisan make:job ImportExpress
php artisan make:job Import
这里我做了个 导入excel表格发货,考虑到用户如果导入数据过多,一直循环下去很可能执行超时,这里使用队列进行操作
在app/Console/Kernel.php中加入生成的队列文件位置
<?php
namespace App\Console;
use App\Jobs\ImportExpress;
use App\Jobs\Export;
use App\Jobs\Import;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
//
// \App\Console\Commands\AddService::class
];
/**
* Define the application's command schedule.
*
* @param Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->job(new ImportExpress)->everyMinute();
$schedule->job(new Import)->everyMinute();
$schedule->job(new Export)->everyMinute();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
在执行 php artisan schedule:run
即可定时执行任务
要实现定时任务还得让程序自动执行
将 * php /path/to/artisan schedule:run >> /dev/null 2>&1
保存到cron.txt文件中
得到文件路径 找到该文件并更改路径 该命令是让PHP每分钟调用一次 Laravel 命令调度器(php artisan schedule:run),接着 Laravel 会评判你的计划任务并运行预定任务。 将文件路径传给crontab,crontab- l执行
四、完整代码实现 路由:
/*订单导入*/
Route::post('Import',[OrderController::class,'OrderImport']);
控制器:这里使用了服务层
/*导入*/
public function OrderImport(Request $request,OrderService $service){
$file = $request->file('file');
try {
if (!empty($file->isValid())) {
$dir = 'upload/excel/'.date("Y_m_d",time());
$filetype = ['xls','xlsx'];
if (!in_array($file->getClientOriginalExtension(),$filetype)){
return response(['error'=>201,"msg"=>"上传文件类型不正确"]);
}
/*文件名。格式:时间戳 + 6位随机数 + 后缀名*/
$filename ='/'.date("H_i_s",time()).'_'.mt_rand(1000, 9999).'.'.$file ->getClientOriginalExtension();
$file->move($dir, $filename);
$allPath=public_path('/'.$dir . $filename);
$PHPReader =new \PHPExcel_Reader_Excel2007();
if (!$PHPReader->canRead($allPath)) {
$PHPReader = new \PHPExcel_Reader_Excel5();
if (!$PHPReader->canRead($allPath)) {
return "格式不正确";
}
}
$phpExcel = $PHPReader->load($allPath);
$currentSheet = $phpExcel->getSheet(0); //读取excel文件中的第一个工作表
$allColumn = $currentSheet->getHighestColumn(); //取得最大的列号
$allRow = $currentSheet->getHighestRow(); //取得一共有多少行
/*导入数据存入缓存 队列发货*/
$data=$service->Import($allColumn,$allRow,$phpExcel);
if($data){
return response(['error'=>200,'data'=>[],'msg'=>"导入成功"]);
}
return response(['error'=>201,'data'=>[],'msg'=>"没有数据"]);
}
return response(['error'=>201,"msg"=>"未识别到文件"]);
}catch (\Exception $e){
return response(['message'=>$e->getMessage(),'error'=>201]);
}
}
服务层:
/*导入表格*/
public function Import(string $allColumn,int $allRow,object $phpExcel):bool
{
$data = [];
for ($j = 2; $j <= $allRow; $j++) {
$i = 0;
$item = [];
Import::dispatch($allColumn,$allRow,$phpExcel,$j,$i,$item);//将复杂表头的表格信息数据重新组装写入缓存
$data[]=json_decode(Cache::get(md5($j)),true) ;
}
if(count($data)>1){
Log::info('_________________________'.date('Y-m-d H:i:s').'导入发货日志_________________________');
foreach ($data as $item){
ImportExpress::dispatch($item);//对列发货
}
return true;
}
return false;
}
队列:写入缓存
<?php
namespace App\Jobs;
use App\Models\OrderGoods;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Cache;
use Matrix\Exception;
class Import implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $allColumn;
private $allRow;
private $phpExcel;
private $j;
private $i;
private $item;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($allColumn,$allRow,$phpExcel,$j,$i,$item)
{
$this->allColumn=$allColumn;
$this->allRow=$allRow;
$this->phpExcel=$phpExcel;
$this->j=$j;
$this->i=$i;
$this->item=$item;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
try {
$allColumn=$this->allColumn;
$allRow=$this->allRow;
$phpExcel=$this->phpExcel;
$j=$this->j;
$i=$this->i;
$item=$this->item;
for ($k = 'A'; $k <= $allColumn; $k++) {
if ($k == 'AA') {
break;
}
if ($k != 'A') {
if ($phpExcel->getActiveSheet()->getCell($k . "1")->getValue() == '快递公司' || $phpExcel->getActiveSheet()->getCell($k . "1")->getValue() == '快递单号' || $phpExcel->getActiveSheet()->getCell($k . "1")->getValue() == '订单商品id') {
switch ($phpExcel->getActiveSheet()->getCell($k . "1")->getValue()) {
case '快递公司':
$item['express_name'] = $phpExcel->getActiveSheet()->getCell("$k$j")->getValue();
break;
case '快递单号':
$item['express_number'] = $phpExcel->getActiveSheet()->getCell("$k$j")->getValue();
break;
default:
$item['order_goods_id'] = (int)$phpExcel->getActiveSheet()->getCell("$k$j")->getValue();
$item['order_id']=OrderGoods::where('id',$item['order_goods_id'])->pluck('order_id')->first();
break;
}
}
}
$i += 1;
}
Log::info(date('Y-m-d H:i:s').'导入发货文件队列 完成 json:'.json_encode($item,JSON_UNESCAPED_UNICODE));
$time=10*60;
Cache::put(md5(json_encode($j)), json_encode($item),$time);
}catch (\Exception $e){
info(date('Y-m-d H:i:s').'导入发货文件队列错误. '.$e->getMessage(),$e->getTrace());
}
}
}
队列:发货
<?php
namespace App\Jobs;
use App\Models\ExpressCompanies;
use App\Models\ExpressLog;
use App\Models\MessageTemplate;
use App\Models\Order;
use App\Models\OrderGoods;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Matrix\Exception;
class ImportExpress implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $item;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($item)
{
$this->item=$item;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
try {
$item=$this->item;
$order_goods = OrderGoods::where('id', $item['order_goods_id'])->first()->toArray();
$express_logs['order_id'] = $order_goods['order_id'];
$express_logs['order_goods_id'] = $item['order_goods_id'];
if(ExpressLog::where($express_logs)->first()){
Log::info(date('Y-m-d H:i:s').'order_id:'.$express_logs['order_id'].' order_goods_id:'.$express_logs['order_goods_id'].' 已发货,请勿重复发货');
}else{
/*事务*/
\DB::transaction(function () use ($item,$order_goods,$express_logs) {
$express_logs['express_company_id'] = ExpressCompanies::where('name', $item['express_name'])->pluck('id')->first();
$express_logs['express_number'] = (string)$item['express_number'];
$express_logs['counts'] = $order_goods['counts'];
/*查询发货记录是否存在 与当前订单id一样且为同一个快递单号 若我则 包数与存在的记录包数一样 */
$order_goods_express = ExpressLog::where('order_id', $order_goods['order_id'])
->where('express_number', $express_logs['express_number'])->first();
if ($order_goods_express) {
$express_logs['package'] = $order_goods_express->package;
} else {
$express_logs['package'] = ExpressLog::where('order_id', $express_logs['order_id'])->max('package') + 1;
}
/*插入快递信息*/
ExpressLog::create($express_logs);
/*修改订单商品 发货等状态*/
OrderGoods::where('id', $item['order_goods_id'])->update(['status' => 1]);
/*修改订单 发货等状态 是否部分发货 是否全部发货*/
$order_goods_ids = OrderGoods::where('order_id', $order_goods['order_id'])->pluck('id')->toArray();
$count = ExpressLog::whereIn('order_goods_id', $order_goods_ids)->count();
if (count($order_goods_ids) == $count) {
/*发货方式 整包 分包 查询该订单下的订单商品数与发后记录数 是否一样且快递单号一样 则为整包 否则分包 */
$ExpressLogWhere['order_id'] = $order_goods['order_id'];
$ExpressLogWhere['express_number'] = $express_logs['express_number'];
if (ExpressLog::where($ExpressLogWhere)->count() == OrderGoods::where('order_id', $order_goods['order_id'])->count()) {
$send_type = 0;
} else {
$send_type = 1;
}
$OrderUpdate = ['status' => 3, 'send_type' => $send_type];
Order::where('id', $order_goods['order_id'])->update($OrderUpdate);
} else {
Order::where('id', $order_goods['order_id'])->update(['status' => 2]);
}
$where['order_id']=$express_logs['order_id'];
$where['order_goods_id']=$express_logs['order_goods_id'];
$ExpressLog=ExpressLog::where($where)->first();
$ExpressLog->user_id=OrderGoods::where('id',$ExpressLog->order_goods_id)->pluck('user_id')->first();
/*模板通知*/
MessageTemplate::batch_customer_refund_change_send($ExpressLog);
Log::info(date('Y-m-d H:i:s').'order_id:'.$express_logs['order_id'].' order_goods_id:'.$express_logs['order_goods_id'].' 成功发货,模板通知:');
});
}
}catch (\Exception $e){
info(date('Y-m-d H:i:s').'导入发货 发货 错误. '.$e->getMessage(),$e->getTrace());
}
}
}
猜你喜欢
基于 Swoole 实现简单的 WebSocket 服务器及客户端
阅读 1199基于 Swoole 实现简单的 WebSocket 服务器及客户端
Git使用
阅读 591Git基本配置/服务器搭建仓库
抖音接入
阅读 1956PHP 接入抖音开放平台
Swoole 实现长连接
阅读 2317Swoole 实现长连接,心跳
Swoole 扩展安装与使用入门
阅读 1774Swoole从入门到实战
Resultful API规范
阅读 701什么是resultful
Layui富文本视频等多功能
阅读 620Layui富文本多功能添加
swoole 极简聊天室
阅读 1156五分钟教你写超简单的swoole聊天室