Laravel队列的实现

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

file

三、生成任务类 队列的任务类都默认放在 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文件中

file 得到文件路径 file 找到该文件并更改路径 file 该命令是让PHP每分钟调用一次 Laravel 命令调度器(php artisan schedule:run),接着 Laravel 会评判你的计划任务并运行预定任务。 将文件路径传给crontab,crontab- l执行 file

四、完整代码实现 路由:

        /*订单导入*/
        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]);
    }
}

服务层: file

    /*导入表格*/
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());
                    }

            }
    }

laravel 具体对列文档 参考任务调度文章

猜你喜欢