第一步,创建一个自定义命令类文件,运行指令
php think make:command Timing
会生成一个app\command\Timing 命令行指令类,根据实际项目内容修改如下示例:
<?php
/**
* 定时任务命令行工具
*
* 本文件定义了一个ThinkPHP命令行命令,用于执行系统定时任务。
* 可通过系统crontab配置定期调用,实现自动化业务处理。
*/
// 开启严格类型模式,确保方法参数和返回值类型严格匹配,提升代码健壮性
declare(strict_types=1);
// 定义命令类所在的命名空间,符合ThinkPHP应用的组织结构
namespace app\command;
// 引入ThinkPHP命令行基础类
use think\console\Command; // 命令行命令基类,所有自定义命令必须继承此类
use think\console\Input; // 输入处理类,用于获取命令行参数和选项
use think\console\Output; // 输出处理类,用于向控制台输出信息
use think\console\input\Argument; // 参数定义类,用于定义位置参数
use think\console\input\Option; // 选项定义类,用于定义命名选项参数
use think\facade\Log; // 日志门面,用于记录执行日志(可选)
/**
* 定时任务执行命令类
*
* 该类继承自ThinkPHP的Command基类,用于创建可被调用的定时任务命令。
* 通过系统cron配置定期执行,实现自动化业务处理。
*
* @package app\command
*/
class Timing extends Command
{
/**
* 配置命令基本信息
*
* 该方法在命令注册时被框架调用,用于设置命令的名称、描述、参数和选项等信息。
* 这些信息会在执行 `php think list` 时显示在命令列表中。
*
* @return void
*/
protected function configure(): void
{
// 设置命令名称,在命令行中通过 `php think timing` 调用
$this->setName('timing')
// 设置命令描述,显示在命令列表中便于识别命令用途
->setDescription('执行系统定时任务,包括数据清理、统计报表生成等自动化作业')
// 添加命令参数定义(示例:可选的执行模式参数)
// 参数格式:Argument::create('参数名', '模式', '描述', '默认值')
// 模式:Argument::REQUIRED(必填) 或 Argument::OPTIONAL(可选)
->addArgument('mode', Argument::OPTIONAL, '任务执行模式(test-测试模式, force-强制模式)', 'normal')
// 添加命令选项定义(示例:是否跳过某些任务的选项)
// 选项格式:Option::create('选项名', '简写', '模式', '描述', '默认值')
// 模式:Option::VALUE_REQUIRED(必须值), Option::VALUE_OPTIONAL(可选值),
// Option::VALUE_NONE(无值,作为开关使用)
->addOption('skip-clean', null, Option::VALUE_NONE, '跳过数据清理任务')
->addOption('verbose', 'v', Option::VALUE_NONE, '显示详细执行信息');
}
/**
* 执行命令的主要逻辑
*
* 当用户在命令行中运行 `php think timing` 时,该方法会被自动调用。
* 包含完整的定时任务业务逻辑,建议将不同任务模块化处理。
*
* @param Input $input 输入对象,用于获取命令行输入的参数和选项值
* @param Output $output 输出对象,用于向控制台输出执行信息和结果
* @return int 返回执行状态码:0-成功,1-失败(遵循Unix惯例)
*/
protected function execute(Input $input, Output $output): int
{
// 输出开始执行提示信息,使用info样式显示绿色文本
$output->writeln('<info>🚀 开始执行定时任务...</info>');
// 获取命令行参数和选项值
$executionMode = $input->getArgument('mode'); // 获取模式参数
$isSkipClean = $input->getOption('skip-clean'); // 获取是否跳过清理的选项
$isVerbose = $input->getOption('verbose'); // 获取是否显示详细信息的选项
// 显示当前执行配置(在详细模式下显示)
if ($isVerbose) {
$output->writeln("📋 执行模式: {$executionMode}");
$output->writeln("⏭️ 跳过清理: " . ($isSkipClean ? '是' : '否'));
}
try {
// 记录开始时间,用于计算任务执行耗时
$startTime = microtime(true);
// ======================= 任务执行区域开始 =======================
// 任务1: 执行数据清理(除非指定了跳过清理选项)
if (!$isSkipClean) {
$output->writeln('🧹 开始执行数据清理任务...');
$this->cleanupData(); // 调用数据清理方法
$output->writeln('<comment>✅ 数据清理完成</comment>');
} else {
$output->writeln('<comment>⏭️ 跳过数据清理任务</comment>');
}
// 任务2: 生成每日统计报表
$output->writeln('📊 开始生成统计报表...');
$reportResult = $this->generateReports(); // 调用报表生成方法
$output->writeln("<comment>✅ 报表生成完成: {$reportResult}条记录</comment>");
// 任务3: 发送通知邮件(仅在非测试模式下执行)
if ($executionMode !== 'test') {
$output->writeln('📧 开始发送通知邮件...');
$sentCount = $this->sendNotifications(); // 调用邮件发送方法
$output->writeln("<comment>✅ 邮件发送完成: {$sentCount}封</comment>");
}
// ======================= 任务执行区域结束 =======================
// 计算并显示总执行时间
$executionTime = round(microtime(true) - $startTime, 2);
$output->writeln("<info>🎉 所有定时任务执行完成!耗时: {$executionTime}秒</info>");
// 记录成功日志(可选)
Log::info("定时任务执行成功 - 模式: {$executionMode}, 耗时: {$executionTime}秒");
// 返回成功状态码
return 0;
} catch (\Exception $e) {
// 捕获执行过程中抛出的异常
$errorMessage = "❌ 定时任务执行失败: " . $e->getMessage();
// 输出错误信息到控制台(红色文本)
$output->writeln("<error>{$errorMessage}</error>");
// 记录详细错误日志,包含堆栈跟踪信息
Log::error("定时任务执行失败: " . $e->getMessage(), [
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString()
]);
// 返回失败状态码 1
return 1;
}
}
/**
* 执行数据清理任务
*
* 清理过期缓存、临时文件、无效数据等
* 实际项目中应根据具体业务需求实现
*
* @return void
*/
private function cleanupData(): void
{
// 示例:清理过期缓存
// Cache::clearExpired();
// 示例:删除临时文件
// $this->deleteTempFiles();
// 示例:清理数据库中的软删除记录
// Model::where('delete_time', '<', time() - 30*86400)->delete();
// 模拟清理操作耗时
sleep(1);
}
/**
* 生成统计报表
*
* 生成各种业务统计报表,如每日订单统计、用户活跃度等
*
* @return int 返回生成的报表记录数
*/
private function generateReports(): int
{
// 示例:生成每日订单统计
// $orderCount = Order::whereDate('create_time', date('Y-m-d'))->count();
// 示例:生成用户活跃度报表
// $activeUsers = User::where('last_login_time', '>', time() - 86400)->count();
// 模拟报表生成操作,返回生成的记录数
sleep(2);
return 15; // 模拟生成15条报表记录
}
/**
* 发送通知邮件
*
* 向相关人员发送任务执行结果通知
*
* @return int 返回成功发送的邮件数量
*/
private function sendNotifications(): int
{
// 示例:发送邮件通知
// $mailer = new Mailer();
// $sent = $mailer->sendDailyReport();
// 模拟邮件发送操作
sleep(1);
return 3; // 模拟发送3封邮件
}
}
第二步,配置config/console.php文件
<?php
return [
'commands' => [
'timing' => 'app\command\Timing',
]
];
第三步,测试,运行命令
php think timing
第四步,添加定时计划任务,具体百度下如何添加计划任务一大堆