## 安裝
> composer require topthink/think-queue
## 配置
> 配置文件位于?`config/queue.php`
### 公共配置
~~~php
[
'default'=>'sync' //驅動類型,可選擇 sync(默認):同步執行,database:數據庫驅動,redis:Redis驅動//或其他自定義的完整的類名
]
~~~
配置消息隊列的驅動
根據選擇的存儲方式,在\\app\\config\\queue.php這個配置文件中,添加消息隊列對應的驅動配置

## 創建任務類
> 單模塊項目推薦使用?`app\job`?作為任務類的命名空間 多模塊項目可用使用?`app\module\job`?作為任務類的命名空間 也可以放在任意可以自動加載到的地方
>
> 任務類不需繼承任何類,如果這個類只有一個任務,那么就只需要提供一個`fire`方法就可以了,如果有多個小任務,就寫多個方法,下面發布任務的時候會有區別
> 每個方法會傳入兩個參數?`think\queue\Job $job`(當前的任務對象) 和?`$data`(發布任務時自定義的數據)
>
> 還有個可選的任務失敗執行的方法?`failed`?傳入的參數為`$data`(發布任務時自定義的數據)
~~~
例一:消息的消費與刪除
namespace app\job;
use think\queue\Job;
class Job1{
public function fire(Job $job, $data){
//....這里執行具體的任務
if ($job->attempts() > 3) {
//通過這個方法可以檢查這個任務已經重試了幾次了
}
//如果任務執行成功后 記得刪除任務,不然這個任務會重復執行,直到達到最大重試次數后失敗后,執行failed方法
$job->delete();
// 也可以重新發布這個任務
$job->release($delay); //$delay為延遲時間
}
public function failed($data){
// ...任務達到最大重試次數后,失敗了
}
}
~~~
~~~
例二:
namespace app\lib\job;
use think\queue\Job;
class Job2{
public function task1(Job $job, $data){
}
public function task2(Job $job, $data){
}
public function failed($data){
}
}
~~~
~~~php
例三:多模塊舉例
~~~
~~~
<?php
/**
* 消息隊列(queue)使用方法
* 使用redis實現消息隊列demo
*/
namespace app\crm\job\export;
use think\facade\Db;
use think\queue\Job;
class QueueJobTest
{
public function fire(Job $job,$data){
// 如有必要,可以根據業務需求和數據庫中的最新數據,判斷該任務是否仍有必要執行.
$isJobStillNeedToBeDone = $this->checkJobNeedIfDone($data);
if(!$isJobStillNeedToBeDone){
//刪除任務
$job->delete();
return;
}
$isJobDone = $this->saveInfo($data);
//如果任務執行完成,刪除此隊列任務,
if($isJobDone){
//刪除任務
$job->delete();
}else{
//通過這個方法可以檢查這個任務已經重試了幾次了
if ($job->attempts() > 3) {
//如果大于設置的次數3,可執行刪除任務或重新發布此任務
//此處直接執行刪除任務
$job->delete();
//--begin-重新發布此任務-------
//$job->release(2); //參數為設置的延遲時間,表示該任務延遲2秒后再執行
//--end-重新發布此任務--------——
}
}
}
/**
* 可選的任務失敗執行的方法,此處只作列舉
* 任務失敗,執行failed方法
* @param $data 發布任務時自定義的數據
*/
//public function failed($data){
//// ...任務達到最大重試次數后,失敗了
//執行失敗的業務代碼
//}
/**
* 有些消息在到達消費者時,可能已經不再需要執行了
* @param array|mixed $data 發布任務時自定義的數據
* @return boolean 任務執行的結果
*/
private function checkJobNeedIfDone($data){
//可查詢數據庫確認是否需要繼續執行,比如訂單支付的狀態更改等后續操作
//此處省略業務邏輯,直接返回true,表示繼續執行
return true;
}
/**
* 任務執行的業務代碼
* 如發送郵件,數據入庫等
*/
private function saveInfo($data){
//此處模擬數據入庫
$res = Db::name('test')->insert(
[
'title' => $data['title'],
'content' => $data['content'],
'add_time' => time()
]
);
if($res){
return true;
}else{
return false;
}
}
}
~~~
## 發布任務
> 兩個方法
>
> `think\facade\Queue::push($job, $data = '', $queue = null);`? //立即執行
>
> 或?
>
> `think\facade\Queue::later($delay, $job, $data = '', $queue = null);`? //延時執行,在參數?`$delay?`秒后執行在`$delay`秒后執行
>
> `$job`?是任務名
> 單模塊的,且命名空間是`app\job`的,比如上面的例子一,寫`Job1`類名即可
> 多模塊的,且命名空間是`app\module\job`的,寫`model/Job1`即可
> 其他的需要些完整的類名,比如上面的例子二,需要寫完整的類名`app\lib\job\Job2`
> 如果一個任務類里有多個小任務的話,如上面的例子二,需要用@+方法名`app\lib\job\Job2@task1`、`app\lib\job\Job2@task2`
>
> `$data`?是你要傳到任務里的參數
>
> `$queue`?隊列名,指定這個任務是在哪個隊列上執行,同下面監控隊列的時候指定的隊列名,可不填
>
> **例:**
>
> ~~~php
> 文件路徑:
>
> ~~~
>
> **任務名(類名):app\\crm\\job\\export\\QueueJobTest**
>
> **傳到任務里的參數:**\['title' => '隊列任務入庫demo','content' => 'xxxx內容'\]****
>
> **隊列名(可不填):queueJobTest**
>
> ****//生產者業務代碼中把任務push到隊列中:****
>
> **think\\facade\\Queue::push('app\\crm\\job\\export\\QueueJobTest',? \['title' => '隊列任務入庫demo','content' => 'xxxx內容'\], '**queueJobTest**')**

**發布任務**
?瀏覽器中訪問:http://localhost/index.php/Test/actionQueueJobTest??
## 監聽任務并執行
消費者進行處理隊列
~~~
&> php think queue:listen
&> php think queue:work
~~~
兩種,具體的可選參數可以輸入命令加?`--help`?查看
**處理任務**
> 方式一:
>
> 切換當前終端窗口的目錄到項目根目錄下,執行
>
> php think queue:work --queue queueJobTest
>
> 或
>
> php think queue:listen --queue queueJobTest
> 方式二:
>
> supervisor安裝參考:https://www.cnblogs.com/chihuobao/p/15341719.html??
>
> 可配合supervisor使用,保證進程常駐
>
> 添加queueJobTest.ini文件輸入如下內容
>
>
> \[program:queueJobTest\]
> user=root
> command = php /home/wwwroot/test\_crm/think queue:listen --queue?queueJobTest --timeout 0 --memory 1024
> autostart=true
> autorestart=false
> stderr\_logfile=/tmp/queue\_stderr.log
> stdout\_logfile=/tmp/queue\_stdout.log
**1、首先,你需要在你的框架中下載queue這個擴展**
~~~
composer require topthink/think-queue
~~~
**2.公共配置,配置文件位于:config/queue.php**
[](javascript:void(0); "復制代碼")
~~~
return [
'default' => 'redis',
'connections' => [
'sync' => [
'type' => 'sync',
],
'database' => [
'type' => 'database',
'queue' => 'default',
'table' => 'jobs',
'connection' => null,
],
'redis' => [
'type' => 'redis',
'queue' => 'default',
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'select' => 0,
'timeout' => 0,
'persistent' => false,
],
],
'failed' => [
'type' => 'none',
'table' => 'failed_jobs',
],
];
~~~
[](javascript:void(0); "復制代碼")
**你可以在配置文件中選擇你需要使用數據庫的類型,根據自己的需求使用,這里我選擇的是redis**
~~~
'default'=>'sync' //驅動類型,可選擇 sync(默認):同步執行,database:數據庫驅動,redis:Redis驅動//或其他自定義的完整的類名
~~~
**3.創建任務類**
**單模塊項目推薦使用?`app\job`?作為任務類的命名空間**
**多模塊項目可用使用?`app\module\job`?作為任務類的命名空間 也可以放在任意可以自動加載到的地方**
**我這里是在? app\\admin\\job? 創建了這個任務類**
**里面執行了我發送郵件的任務,這里的例子可以實現延遲發送郵件的任務**
**示例代碼如下**
[](javascript:void(0); "復制代碼")
~~~
<?php
namespace app\admin\job;
use think\facade\Log;
use think\queue\Job;
use tool\SendMail;
class Test
{
public function fire(Job $job, $data){
if ($job->attempts()>3){
//執行失敗寫入錯誤日志
Log::error('fire執行失敗');
//刪除這個任務
$job->delete();
}else{
$toemail="407489255@qq.com"; //定義收件人的郵箱
$username="407486225@qq.com"; //發送方的郵箱地址
$password="qmxrvjgohiucbbgj"; //發送方郵箱的密碼
$setFrom="1223524552@qq.com"; //設置發件人信息
$addReplyTo="1003729782@qq.com"; //設置收件人信息
$contrnt="郵件內容是 <b>您的驗證碼是:123456</b>,哈哈哈!111122"; //設置郵件內容
SendMail::sendMail($toemail,$username,$password,$setFrom,$addReplyTo,$contrnt);
//執行成功刪除這個任務
$job->delete();
}
}
}
~~~
[](javascript:void(0); "復制代碼")
~~~
這個是發送郵件的封住類 配合上面的使用
~~~
[](javascript:void(0); "復制代碼")
~~~
<?php
namespace tool;
use PHPMailer\PHPMailer\PHPMailer;
class SendMail
{
public static function sendMail($toemail,$username,$password,$setFrom,$addReplyTo,$contrnt)
{
$toemail ="$toemail";//定義收件人的郵箱
$mail = new PHPMailer();
$mail->isSMTP();// 使用SMTP服務
$mail->CharSet = "utf8";// 編碼格式為utf8,不設置編碼的話,中文會出現亂碼
$mail->Host = "smtp.qq.com";// 發送方的SMTP服務器地址
$mail->SMTPAuth = true;// 是否使用身份驗證
$mail->Username = "$username";// 發送方的163郵箱用戶名,就是你申請163的SMTP服務使用的163郵箱</span><span style="color:#333333;">
$mail->Password = "$password";// 發送方的郵箱密碼,注意用163郵箱這里填寫的是“客戶端授權密碼”而不是郵箱的登錄密碼!</span><span style="color:#333333;">
$mail->SMTPSecure = "ssl";// 使用ssl協議方式</span><span style="color:#333333;">
$mail->Port = 465;// 163郵箱的ssl協議方式端口號是465/994
$mail->setFrom("$setFrom", "Mailer");// 設置發件人信息,如郵件格式說明中的發件人,這里會顯示為Mailer(xxxx@163.com),Mailer是當做名字顯示
$mail->addAddress($toemail, 'Wang');// 設置收件人信息,如郵件格式說明中的收件人,這里會顯示為Liang(yyyy@163.com)
$mail->addReplyTo("$addReplyTo", "Reply");// 設置回復人信息,指的是收件人收到郵件后,如果要回復,回復郵件將發送到的郵箱地址
//$mail->addCC("xxx@163.com");// 設置郵件抄送人,可以只寫地址,上述的設置也可以只寫地址(這個人也能收到郵件)
//$mail->addBCC("xxx@163.com");// 設置秘密抄送人(這個人也能收到郵件)
//$mail->addAttachment("bug0.jpg");// 添加附件
$mail->Subject = "這是一個測試郵件";// 郵件標題
$mail->Body = "$contrnt";// 郵件正文
//$mail->AltBody = "This is the plain text純文本";// 這個是設置純文本方式顯示的正文內容,如果不支持Html方式,就會用到這個,基本無用
if (!$mail->send()) {// 發送郵件
echo "Message could not be sent.";
echo "Mailer Error: " . $mail->ErrorInfo;// 輸出錯誤信息
} else {
echo '發送成功';
}
}
}
~~~
[](javascript:void(0); "復制代碼")
**4.發布任務? ?控制器調用這個? 進入發布任務**
[](javascript:void(0); "復制代碼")
~~~
<?php
declare (strict_types = 1);
namespace app\admin\controller;
use think\facade\Queue;
use think\Request;
class index
{
/**
* 顯示資源列表
*
* @return \think\Response
*/
public function index()
{
//設置執行這個任務
Queue::later('20','app\admin\job\Test@fire',['name'=>'Test'],'fire');
}
~~~
[](javascript:void(0); "復制代碼")
~~~
注:一寫參數的解釋與使用方法
~~~
> `think\facade\Queue::push($job, $data = '', $queue = null)`?和?`think\facade\Queue::later($delay, $job, $data = '', $queue = null)`?兩個方法,前者是立即執行,后者是在`$delay`秒后執行
`$job`?是任務名
單模塊的,且命名空間是`app\job`的,比如上面的例子一,寫`Job1`類名即可
多模塊的,且命名空間是`app\module\job`的,寫`model/Job1`即可
其他的需要些完整的類名,比如上面的例子二,需要寫完整的類名`app\lib\job\Job2`
如果一個任務類里有多個小任務的話,如上面的例子二,需要用@+方法名`app\lib\job\Job2@task1`、`app\lib\job\Job2@task2`
`$data`?是你要傳到任務里的參數
`$queue`?隊列名,指定這個任務是在哪個隊列上執行,同下面監控隊列的時候指定的隊列名,可不填
## 5.監聽任務并執行
這是我的執行的方法
~~~
php think queue:listen --queue fire
~~~
**參數解釋**
> php think queue:listen
> php think queue:work
兩種,具體的可選參數可以輸入命令加 --help 查看
> 可配合supervisor使用,保證進程常駐
- thinkphp6執行流程(一)
- php中use關鍵字用法詳解
- Thinkphp6使用騰訊云發送短信步驟
- 路由配置
- Thinkphp6,static靜態資源訪問路徑問題
- ThinkPHP6.0+ 使用Redis 原始用法
- smarty在thinkphp6.0中的最佳實踐
- Thinkphp6.0 搜索器使用方法
- 從已有安裝包(vendor)恢復 composer.json
- tp6with的用法,表間關聯查詢
- thinkphp6.x多對多如何添加中間表限制條件
- thinkphp6 安裝JWT
- 緩存類型
- 請求信息和HTTP頭信息
- 模型事件用法
- 助手函數匯總
- tp6集成Alipay 手機和電腦端支付的方法
- thinkphp6使用jwt
- 6.0session cookie cache
- tp6筆記
- TP6(thinkphp6)隊列與延時隊列
- thinkphp6 command(自定義指令)
- command(自定義指令)
- 本地文件上傳
- 緩存
- 響應
- 公共函數配置
- 七牛云+文件上傳
- thinkphp6:訪問多個redis數據源(thinkphp6.0.5 / php 7.4.9)
- 富文本編輯器wangEditor3
- IP黑名單
- 增刪改查 +文件上傳
- workerman 定時器操作控制器的方法
- 上傳文件到阿里云oss
- 短信或者郵箱驗證碼防刷代碼
- thinkphp6:訪問redis6(thinkphp 6.0.9/php 8.0.14)
- 實現關聯多個id以逗號分開查詢數據
- thinkphp6實現郵箱注冊功能的細節和代碼(點擊鏈接激活方式)
- 用mpdf生成pdf文件(php 8.1.1 / thinkphp v6.0.10LTS )
- 生成帶logo的二維碼(php 8.1.1 / thinkphp v6.0.10LTS )
- mysql數據庫使用事務(php 8.1.1 / thinkphp v6.0.10LTS)
- 一,創建過濾IP的中間件
- 源碼解析請求流程
- 驗證碼生成
- 權限管理
- 自定義異常類
- 事件監聽event-listene
- 安裝與使用think-addons
- 事件與多應用
- Workerman 基本使用
- 查詢用戶列表按拼音字母排序
- 擴展包合集
- 查詢用戶數據,但是可以通過輸入用戶昵稱來搜索用戶同時還要統計用戶的文章和粉絲數
- 根據圖片的minetype類型獲取文件真實拓展名思路
- 到處excel
- 用imagemagick庫生成縮略圖
- 生成zip壓縮包并下載
- API 多版本控制
- 用redis+lua做限流(php 8.1.1 / thinkphp v6.0.10LTS )
- 【thinkphp6源碼分析三】 APP類之父, 容器Container類
- thinkphp6表單重復提交解決辦法
- 小程序授權
- 最簡單的thinkphp6導出Excel
- 根據訪問設備不同訪問不同模塊
- 服務系統
- 前置/后置中間件
- 給接口api做簽名驗證(php 8.1.1 / thinkphp v6.0.10LTS )
- 6實現郵箱注冊功能的細節和代碼(點擊鏈接激活方式)
- 使用前后端分離的驗證碼(thinkphp 6.0.9/php 8.0.14/vue 3.2.26)
- 前后端分離:用jwt+middleware做用戶登錄驗證(php 8.1.1 / thinkphp v6.0.10LTS )
- vue前后端分離多圖上傳
- thinkphp 分組、頁面跳轉與ajax
- thinkphp6 常用方法文檔
- 手冊里沒有的一些用法
- Swagger 3 API 注釋
- PHP 秒級定時任務
- thinkphp6集成gatewayWorker(workerman)實現實時監聽
- thinkphp6按月新增數據表
- 使用redis 實現消息隊列
- api接口 統一結果返回處理類
- 使用swoole+thinkphp6.0+redis 結合開發的登錄模塊
- 給接口api做簽名驗證
- ThinkPHP6.0 + UniApp 實現小程序的 微信登錄
- ThinkPHP6.0 + Vue + ElementUI + axios 的環境安裝到實現 CURD 操作!
- 異常$e
- 參數請求驗證自定義和異常錯誤自定義