必须手动开启调度器并严格编写命令类:在console.php中设置'scheduling' => true;命令类需置于app/command/下、命名空间为app\command、继承think\console\Command、setName无空格、execute含业务逻辑。

要在ThinkPHP8项目中让清理缓存、同步数据或发送通知等任务按时自动执行,必须把业务逻辑封装成命令行指令,并由Linux系统级定时器(crontab)每分钟主动调用一次php think schedule:run来扫描并触发,缺一不可。
启用框架调度器
ThinkPHP8默认不启用任务调度功能,必须手动开启,否则schedule:run命令永远显示“No scheduled commands are ready to run”。
打开app/config/console.php文件,在配置数组中添加或确认存在这一行:【'scheduling' => true】。
这一步漏掉,后续所有配置都无效——框架根本不会加载调度逻辑,连任务注册表都不会初始化。
立即学习“PHP免费学习笔记(深入)”;
编写可被调度的命令类
不是所有命令都能进调度队列。必须满足四个硬性条件,缺一不可。
第一步:在app/command/目录下新建PHP文件,例如SyncUserCommand.php(注意是小写command,不是Console/Commands)。
第二步:文件内容严格按以下结构编写:
命名空间必须为app\command;
继承think\console\Command;
在configure()方法中调用$this->setName('sync:user'),名称不能含空格或特殊字符;
在execute()方法里写真实业务逻辑,例如Db::table('user')->where('updated_at', 'subHour())->update(['status' => 1]);;
返回self::SUCCESS,严禁使用exit()或die(),否则会中断整个调度流程。
注册命令到框架
ThinkPHP8不再自动扫描app/command/目录,必须显式注册,否则php think list里根本看不到你的命令。
打开或新建app/command.php文件,确保它返回一个数组,且包含完整类名字符串:
<?php return ['app\command\SyncUserCommand'];
PHP 8.5.12 RC 1 候选版修复 BZ2、DOM、PDO、Opcache/JIT 和扩展内存安全问题,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
多个命令就逐个写进去,不能省略命名空间,不能写别名,空数组也得写return [];。
配置Linux crontab触发
这才是让任务真正“定时”的环节。crontab运行环境与你的shell完全不同,路径、环境变量、工作目录全都不一样。
方法一:直接调用schedule:run(推荐)
执行crontab -e,添加这一行:
*/1 * * * * cd /var/www/myproject && /usr/bin/php think schedule:run >> /var/log/think-schedule.log 2>&1
【cd /var/www/myproject必须写,否则自动加载失败、.env读不到、runtime目录权限错乱】
方法二:手动指定PHP路径并重定向日志
先用which php确认实际PHP解释器路径,比如是/opt/php/bin/php;
再用绝对路径写crontab条目,日志路径也必须绝对化,例如/var/log/myapp-cron.log;
测试时先写最简命令:* * * * * cd /var/www/myproject && /usr/bin/php think test:ping >> /tmp/cron-test.log 2>&1,等一分钟看日志是否输出。
开发环境手动验证
别跳过本地测试,90%的线上失败都源于这步没做。
在项目根目录执行:php think list,确认输出里有sync:user;
再执行:php think sync:user,观察是否正常运行;
如果报Class not found,立刻检查三处:文件路径是否真在app/command/下、命名空间是否为app\command、app/command.php里是否完整注册了类名。
手动运行调度器需加环境变量:APP_ENV=local php think schedule:run -v,否则默认跳过执行。


















