使用消息队列(queue)是一种异步的处理方式,可以将一些延时处理的任务放到消息队列中进行,这种方式可以减轻同步处理的压力,提高处理效率。Laravel框架中提供了轻量级的队列系统以跟消息队列(queue)进行交互,自带的队列驱动包括数据库,Redis,Amazon SQS等。
下面是使用Laravel框架消息队列(queue)及异步队列的方法:
1. 安装队列驱动
Laravel中提供很多队列驱动,这里以Redis驱动为例进行说明。
1.1 安装predis包:predis是php操作redis的优秀封装库,使用composer安装即可。
composer require predis/predis
1.2 配置队列驱动:在 .env 配置中增加以下配置
QUEUE_DRIVER=redis # 配置Redis队列
REDIS_HOST=127.0.0.1 # Redis地址
REDIS_PASSWORD=null # Redis密码,无密码情况下设置为null
REDIS_PORT=6379 # Redis端口号
REDIS_DATABASE=0 # Redis数据库,默认为0
2. 创建任务
创建一个任务类并实现 ShouldQueue
接口,注意类名必须以 Job
结尾。可以在任务类的 handle()
方法中定义需要执行的代码,例如向用户发送邮件、上传图片到云存储等操作。
示例代码:
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SendReminderEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
// 处理发送邮件的逻辑
}
}
3. 将任务放入队列
我们可以使用 dispatch()
函数来将我们创建的任务类放入Laravel队列。对于一些可以异步执行的操作,就可以使用这种方式来进行处理,让用户不用等待操作完成就可以进行其他操作。
示例代码:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Jobs\SendReminderEmail;
class ExampleController extends Controller
{
/**
* Send a reminder email.
*
* @param int $userId
* @return Response
*/
public function sendReminderEmail($userId)
{
dispatch(new SendReminderEmail($userId));
}
}
4. 执行队列任务
执行队列任务使用Artisan命令 queue:work
命令,该命令允许开启一个后台的进程对任务队列进行处理。
php artisan queue:work
以上就是Laravel框架中使用消息队列queue及异步队列的方法,使用队列可以提高应用程序的处理性能和用户体验。
另外,下方有一些额外的示例,用于更详细地理解如何使用Laravel队列。
示例1
使用 redis 队列,将 CSV 文件导入到数据库中。
- 创建待执行任务
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
class ImportCsv implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $header;
protected $data;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(Collection $data)
{
$this->header = $data->first();
unset($data[0]);
$this->data = $data;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$data = $this->data->toArray();
$data = array_map(function($item) {
return array_combine($this->header, $item);
}, $data);
DB::table('mytable')->insert($data);
}
}
- 创建控制器
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use App\Jobs\ImportCsv;
class ImportCsvController extends Controller
{
public function importCsv(Request $request)
{
$file = $request->file('file');
$header = null;
$data = new Collection();
if (($handle = fopen($file->getRealPath(), "r")) !== FALSE) {
while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) {
if(!$header) {
$header = $row;
} else {
$data->push($row);
}
}
fclose($handle);
}
dispatch(new ImportCsv($data));
}
}
- 创建路由
Route::post('/import-csv', 'ImportCsvController@importCsv');
- 导入CSV
通过postman工具模拟上传一个CSV文件,执行导入。可以看到后台运行了一个导入任务,CSV数据被写到了数据库中。
示例2
异步发送邮件。
- 创建邮件任务
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class SendMail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $to;
protected $subject;
protected $body;
/**
* Create a new job instance.
*
* @param string $to
* @param string $subject
* @param string $body
* @return void
*/
public function __construct(string $to, string $subject, string $body)
{
$this->to = $to;
$this->subject = $subject;
$this->body = $body;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
Mail::send([], [], function ($message) {
$message->to($this->to)
->subject($this->subject)
->setBody($this->body, 'text/html');
});
}
}
- 创建控制器
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Jobs\SendMail;
class MailController extends Controller
{
public function send(Request $request)
{
$to = $request->input('to');
$subject = $request->input('subject');
$body = $request->input('body');
dispatch(new SendMail($to, $subject, $body));
}
}
- 创建路由
Route::post('/send-mail', 'MailController@send');
- 发送邮件
通过postman工具模拟发送邮件,可以看到后台执行了一个发送邮件任务,邮件被异步发送。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:PHP的Laravel框架中使用消息队列queue及异步队列的方法 - Python技术站