早安!接上回,既然我们之前聊了 API 和中间件,今天我们来攻克一个让很多 PHP 开发者(特别是习惯了写网页的开发者)感到陌生但极其强大的领域:ThinkCMF 的命令行模式(Console)与定时任务。
在实际项目中,你是否遇到过这样的尴尬:
- 想批量发送 10,000 封营销邮件,结果网页转了 30 秒就报
504 Gateway Time-out? - 需要每天凌晨 2 点自动统计昨天的报表,却只能苦哈哈地定个闹钟爬起来点一下"生成"按钮?
📅 今日知识点:利用 Console 命令行处理"后台重活"
核心逻辑:
PHP 不仅仅是为了响应浏览器请求(HTTP)而生的,它在命令行(CLI)模式下同样强大。ThinkCMF(基于 ThinkPHP)内置了强大的 Console 组件,允许你编写自定义指令,跳过 Nginx/Apache 的超时限制,直接在服务器后台跑任务。
1. 为什么要用命令行?
- 无超时限制:脚本可以跑几分钟甚至几小时,适合数据迁移、备份。
- 自动化:配合 Linux 的 Crontab,实现"无人值守"的自动化运行。
- 安全:这些逻辑不暴露在公网 URL 上,黑客扫不到。
2. 实战:写一个"清理过期日志"的命令
假设我们需要一个命令,清理 30 天前的临时文件。
第一步:创建命令类
在 app/command 目录下新建 ClearLogs.php(如果是 ThinkCMF 5.1,目录可能略有不同,但逻辑一致):
php
namespace app\command;
use think\console\Command;
use think\console\Input;
use think\console\Output;
class ClearLogs extends Command
{
// 配置指令
protected function configure()
{
// setName 设置指令名称,例如 php think cmf:clear_logs
$this->setName('cmf:clear_logs')
->setDescription('清理30天前的系统日志文件');
}
// 执行逻辑
protected function execute(Input $input, Output $output)
{
$output->writeln("开始清理任务...");
// 模拟清理逻辑
// 这里可以调用你的 Service 或 Model
// $count = \app\portal\service\LogService::clearOld(30);
// 假装清理了 100 条
$output->writeln("任务完成!成功清理了 100 条过期日志。");
}
}
第二步:注册指令
在 config/console.php 中注册你的命令:
php
return [
'commands' => [
'app\command\ClearLogs',
],
];
第三步:运行它!
打开终端(Terminal),进入项目根目录,输入:
bash
php think cmf:clear_logs
你会看到屏幕输出:"任务完成!成功清理了 100 条过期日志。" ------ 不需要浏览器,瞬间完成!
💡 进阶:如何让它"自动"运行(Crontab)?
写好了命令,怎么让它每天凌晨 2 点自己动?这时候需要配合 Linux 的 Crontab。
输入 crontab -e,添加一行:
bash
# 每天凌晨 02:00 执行
0 2 * * * /usr/bin/php /www/wwwroot/yoursite/think cmf:clear_logs >> /tmp/cron_log.txt 2>&1
/usr/bin/php:你的 PHP 执行路径。/www/wwwroot/yoursite/think:你的项目根目录下的 think 文件。
⚠️ 开发小贴士
- 内存泄漏 :如果你在命令行里做死循环(比如常驻内存的消息队列消费者),记得用
unset()及时释放大数组,否则内存会爆炸。 - 权限问题 :命令行运行的用户通常是
root,生成的日志文件权限可能会变成root,导致 Web 端(通常是www用户)无法写入。记得处理好文件权限。
今日金句: 浏览器是给用户看的,命令行才是服务器的"后台总控室"。学会 CLI,你才能掌控服务器的每一分钟。