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 扩展安装与使用入门
阅读 2114Swoole从入门到实战
Laravel验证码
阅读 899Composer生成Laravel验证码
Layui富文本视频等多功能
阅读 886Layui富文本多功能添加
微擎常用记录
阅读 928微擎常用记录
抖音接入
阅读 2255PHP 接入抖音开放平台
基于 Swoole 实现简单的 WebSocket 服务器及客户端
阅读 1553基于 Swoole 实现简单的 WebSocket 服务器及客户端
Resultful API规范
阅读 993什么是resultful
黑客、后门
阅读 1810留下的网站后门,可以作什么?