TP6定時(shí)任務(wù) 2025-09-05

第一步,創(chuàng)建一個(gè)自定義命令類文件,運(yùn)行指令

php think make:command Timing

會(huì)生成一個(gè)app\command\Timing 命令行指令類,根據(jù)實(shí)際項(xiàng)目?jī)?nèi)容修改如下示例:

<?php

/**
 * 定時(shí)任務(wù)命令行工具
 *
 * 本文件定義了一個(gè)ThinkPHP命令行命令,用于執(zhí)行系統(tǒng)定時(shí)任務(wù)。
 * 可通過系統(tǒng)crontab配置定期調(diào)用,實(shí)現(xiàn)自動(dòng)化業(yè)務(wù)處理。
 */

// 開啟嚴(yán)格類型模式,確保方法參數(shù)和返回值類型嚴(yán)格匹配,提升代碼健壯性
declare(strict_types=1);

// 定義命令類所在的命名空間,符合ThinkPHP應(yīng)用的組織結(jié)構(gòu)
namespace app\command;

// 引入ThinkPHP命令行基礎(chǔ)類
use think\console\Command;     // 命令行命令基類,所有自定義命令必須繼承此類
use think\console\Input;       // 輸入處理類,用于獲取命令行參數(shù)和選項(xiàng)
use think\console\Output;      // 輸出處理類,用于向控制臺(tái)輸出信息
use think\console\input\Argument;  // 參數(shù)定義類,用于定義位置參數(shù)
use think\console\input\Option;    // 選項(xiàng)定義類,用于定義命名選項(xiàng)參數(shù)
use think\facade\Log;          // 日志門面,用于記錄執(zhí)行日志(可選)

/**
 * 定時(shí)任務(wù)執(zhí)行命令類
 *
 * 該類繼承自ThinkPHP的Command基類,用于創(chuàng)建可被調(diào)用的定時(shí)任務(wù)命令。
 * 通過系統(tǒng)cron配置定期執(zhí)行,實(shí)現(xiàn)自動(dòng)化業(yè)務(wù)處理。
 *
 * @package app\command
 */
class Timing extends Command
{
    /**
     * 配置命令基本信息
     *
     * 該方法在命令注冊(cè)時(shí)被框架調(diào)用,用于設(shè)置命令的名稱、描述、參數(shù)和選項(xiàng)等信息。
     * 這些信息會(huì)在執(zhí)行 `php think list` 時(shí)顯示在命令列表中。
     *
     * @return void
     */
    protected function configure(): void
    {
        // 設(shè)置命令名稱,在命令行中通過 `php think timing` 調(diào)用
        $this->setName('timing')
            // 設(shè)置命令描述,顯示在命令列表中便于識(shí)別命令用途
            ->setDescription('執(zhí)行系統(tǒng)定時(shí)任務(wù),包括數(shù)據(jù)清理、統(tǒng)計(jì)報(bào)表生成等自動(dòng)化作業(yè)')
            // 添加命令參數(shù)定義(示例:可選的執(zhí)行模式參數(shù))
            // 參數(shù)格式:Argument::create('參數(shù)名', '模式', '描述', '默認(rèn)值')
            // 模式:Argument::REQUIRED(必填) 或 Argument::OPTIONAL(可選)
            ->addArgument('mode', Argument::OPTIONAL, '任務(wù)執(zhí)行模式(test-測(cè)試模式, force-強(qiáng)制模式)', 'normal')
            // 添加命令選項(xiàng)定義(示例:是否跳過某些任務(wù)的選項(xiàng))
            // 選項(xiàng)格式:Option::create('選項(xiàng)名', '簡(jiǎn)寫', '模式', '描述', '默認(rèn)值')
            // 模式:Option::VALUE_REQUIRED(必須值), Option::VALUE_OPTIONAL(可選值),
            //       Option::VALUE_NONE(無值,作為開關(guān)使用)
            ->addOption('skip-clean', null, Option::VALUE_NONE, '跳過數(shù)據(jù)清理任務(wù)')
            ->addOption('verbose', 'v', Option::VALUE_NONE, '顯示詳細(xì)執(zhí)行信息');
    }

    /**
     * 執(zhí)行命令的主要邏輯
     *
     * 當(dāng)用戶在命令行中運(yùn)行 `php think timing` 時(shí),該方法會(huì)被自動(dòng)調(diào)用。
     * 包含完整的定時(shí)任務(wù)業(yè)務(wù)邏輯,建議將不同任務(wù)模塊化處理。
     *
     * @param Input $input 輸入對(duì)象,用于獲取命令行輸入的參數(shù)和選項(xiàng)值
     * @param Output $output 輸出對(duì)象,用于向控制臺(tái)輸出執(zhí)行信息和結(jié)果
     * @return int 返回執(zhí)行狀態(tài)碼:0-成功,1-失?。ㄗ裱璘nix慣例)
     */
    protected function execute(Input $input, Output $output): int
    {
        // 輸出開始執(zhí)行提示信息,使用info樣式顯示綠色文本
        $output->writeln('<info>?? 開始執(zhí)行定時(shí)任務(wù)...</info>');

        // 獲取命令行參數(shù)和選項(xiàng)值
        $executionMode = $input->getArgument('mode');      // 獲取模式參數(shù)
        $isSkipClean = $input->getOption('skip-clean');    // 獲取是否跳過清理的選項(xiàng)
        $isVerbose = $input->getOption('verbose');         // 獲取是否顯示詳細(xì)信息的選項(xiàng)

        // 顯示當(dāng)前執(zhí)行配置(在詳細(xì)模式下顯示)
        if ($isVerbose) {
            $output->writeln("?? 執(zhí)行模式: {$executionMode}");
            $output->writeln("??  跳過清理: " . ($isSkipClean ? '是' : '否'));
        }

        try {
            // 記錄開始時(shí)間,用于計(jì)算任務(wù)執(zhí)行耗時(shí)
            $startTime = microtime(true);

            // ======================= 任務(wù)執(zhí)行區(qū)域開始 =======================

            // 任務(wù)1: 執(zhí)行數(shù)據(jù)清理(除非指定了跳過清理選項(xiàng))
            if (!$isSkipClean) {
                $output->writeln('?? 開始執(zhí)行數(shù)據(jù)清理任務(wù)...');
                $this->cleanupData();  // 調(diào)用數(shù)據(jù)清理方法
                $output->writeln('<comment>? 數(shù)據(jù)清理完成</comment>');
            } else {
                $output->writeln('<comment>??  跳過數(shù)據(jù)清理任務(wù)</comment>');
            }

            // 任務(wù)2: 生成每日統(tǒng)計(jì)報(bào)表
            $output->writeln('?? 開始生成統(tǒng)計(jì)報(bào)表...');
            $reportResult = $this->generateReports();  // 調(diào)用報(bào)表生成方法
            $output->writeln("<comment>? 報(bào)表生成完成: {$reportResult}條記錄</comment>");

            // 任務(wù)3: 發(fā)送通知郵件(僅在非測(cè)試模式下執(zhí)行)
            if ($executionMode !== 'test') {
                $output->writeln('?? 開始發(fā)送通知郵件...');
                $sentCount = $this->sendNotifications();  // 調(diào)用郵件發(fā)送方法
                $output->writeln("<comment>? 郵件發(fā)送完成: {$sentCount}封</comment>");
            }

            // ======================= 任務(wù)執(zhí)行區(qū)域結(jié)束 =======================

            // 計(jì)算并顯示總執(zhí)行時(shí)間
            $executionTime = round(microtime(true) - $startTime, 2);
            $output->writeln("<info>?? 所有定時(shí)任務(wù)執(zhí)行完成!耗時(shí): {$executionTime}秒</info>");

            // 記錄成功日志(可選)
            Log::info("定時(shí)任務(wù)執(zhí)行成功 - 模式: {$executionMode}, 耗時(shí): {$executionTime}秒");

            // 返回成功狀態(tài)碼
            return 0;

        } catch (\Exception $e) {
            // 捕獲執(zhí)行過程中拋出的異常
            $errorMessage = "? 定時(shí)任務(wù)執(zhí)行失敗: " . $e->getMessage();

            // 輸出錯(cuò)誤信息到控制臺(tái)(紅色文本)
            $output->writeln("<error>{$errorMessage}</error>");

            // 記錄詳細(xì)錯(cuò)誤日志,包含堆棧跟蹤信息
            Log::error("定時(shí)任務(wù)執(zhí)行失敗: " . $e->getMessage(), [
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            // 返回失敗狀態(tài)碼 1
            return 1;
        }
    }

    /**
     * 執(zhí)行數(shù)據(jù)清理任務(wù)
     *
     * 清理過期緩存、臨時(shí)文件、無效數(shù)據(jù)等
     * 實(shí)際項(xiàng)目中應(yīng)根據(jù)具體業(yè)務(wù)需求實(shí)現(xiàn)
     *
     * @return void
     */
    private function cleanupData(): void
    {
        // 示例:清理過期緩存
        // Cache::clearExpired();

        // 示例:刪除臨時(shí)文件
        // $this->deleteTempFiles();

        // 示例:清理數(shù)據(jù)庫中的軟刪除記錄
        // Model::where('delete_time', '<', time() - 30*86400)->delete();

        // 模擬清理操作耗時(shí)
        sleep(1);
    }

    /**
     * 生成統(tǒng)計(jì)報(bào)表
     *
     * 生成各種業(yè)務(wù)統(tǒng)計(jì)報(bào)表,如每日訂單統(tǒng)計(jì)、用戶活躍度等
     *
     * @return int 返回生成的報(bào)表記錄數(shù)
     */
    private function generateReports(): int
    {
        // 示例:生成每日訂單統(tǒng)計(jì)
        // $orderCount = Order::whereDate('create_time', date('Y-m-d'))->count();

        // 示例:生成用戶活躍度報(bào)表
        // $activeUsers = User::where('last_login_time', '>', time() - 86400)->count();

        // 模擬報(bào)表生成操作,返回生成的記錄數(shù)
        sleep(2);
        return 15; // 模擬生成15條報(bào)表記錄
    }

    /**
     * 發(fā)送通知郵件
     *
     * 向相關(guān)人員發(fā)送任務(wù)執(zhí)行結(jié)果通知
     *
     * @return int 返回成功發(fā)送的郵件數(shù)量
     */
    private function sendNotifications(): int
    {
        // 示例:發(fā)送郵件通知
        // $mailer = new Mailer();
        // $sent = $mailer->sendDailyReport();

        // 模擬郵件發(fā)送操作
        sleep(1);
        return 3; // 模擬發(fā)送3封郵件
    }
}

第二步,配置config/console.php文件

<?php
return [
    'commands' => [
        'timing' => 'app\command\Timing',
    ]
];

第三步,測(cè)試,運(yùn)行命令

php think timing

第四步,添加定時(shí)計(jì)劃任務(wù),具體百度下如何添加計(jì)劃任務(wù)一大堆

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容