thinkphp 6.1+ 自定义命令需手动注册:安装 think-command、继承正确基类、命名空间为 app\command、在 app/command.php 中显式添加类名;configure() 中禁用容器调用,移至 execute();schedule 异常默认静默,需设 'catch' => false 或加错误处理器;queue:work 默认单次执行,持续监听需 --daemon(开发)或 --once(生产)。

ThinkPHP 6.1+ 升级后 php think 命令不识别自定义指令
升级到 ThinkPHP 6.1 或更高版本后,原来写在 app/command/ 下的自定义命令类不再被自动扫描,php think list 看不到你的指令,执行直接报 Command not found。
根本原因是 TP 6.1 起废弃了旧版命令自动发现机制,改用 think-command 扩展包统一管理,且要求显式注册。
- 确认是否已安装
topthink/think-command(TP 6.1+ 默认不内置):运行composer require topthink/think-command - 检查命令类是否继承
think\console\Command(不是旧版的think\console\command\Command) - 确保类命名空间为
app\command,且文件名与类名严格一致(如SendEmail.php→class SendEmail) - 在
app/command.php配置文件中手动注册:添加'app\command\SendEmail'到数组里(该文件需存在,不存在就新建)
执行 php think schedule:run 报错 Call to undefined method think\Console::make()
这是典型的生命周期钩子调用时机错误——你在命令类的 configure() 或构造函数里,提前调用了容器方法(比如 $this->app->make()),但此时应用实例尚未完全初始化。
ThinkPHP 6.2+ 的 Console 生命周期中,$this->app 在 execute() 方法内才真正可用;configure() 阶段只保证基础命令元信息加载,容器未就绪。
- 把所有依赖注入、服务获取逻辑从
configure()或__construct()挪到execute()方法开头 - 若需在
configure()中设置描述或选项,只能用静态值,不能调用$this->app或任何需容器支持的方法 - 调度任务中若用到了模型或 Db,务必确认它们是在
execute()内首次访问,而非类属性初始化时
定时任务 schedule:run 执行成功但实际逻辑没跑
表面看命令返回 “OK”,日志也显示 “Run the task”,但数据库没更新、邮件没发、队列没推——大概率是任务闭包或回调里抛了异常,却被 Schedule 默认静默吞掉。
TP 的 think-scheduler 在非调试模式下会捕获所有异常并记录到 runtime/log/schedule/,但不会输出到控制台,也不中断主流程,容易误判为“执行成功”。
- 临时加一句
set_error_handler(function($e) { throw $e; });到任务闭包开头,强制暴露错误 - 检查
config/schedule.php中是否设置了'catch' => false(默认是true),设为false可让异常透出 - 确认任务中调用的模型方法没有隐式依赖未加载的中间件或配置(比如用了
auth门面但没初始化 Auth 组件) - 如果用了
->onOneServer(),确保当前机器有且仅有一个schedule:run进程在跑,否则可能被其他节点抢占锁
php think queue:work 启动后立刻退出,无报错
这不是挂了,是队列进程默认以「单次消费」模式运行:处理完一条就退出。你看到它闪退,其实是正常行为,不是 bug。
想让它持续监听,必须加 --daemon 参数(TP 6.0+)或改用 --once / --delay 显式控制行为;另外,新版对 Redis 连接复用更敏感,连接泄漏会导致后续请求卡住。
- 启动常驻进程:用
php think queue:work --daemon --queue=high,default - 避免在任务中手动
new \Redis()或PDO,优先走容器获取(如$this->app->get('redis')),否则连接不归还 - 检查
config/queue.php中'retry_after'是否设得太小(如 1 秒),导致任务刚取出来就被标记为失败重推 - 如果用的是 database 驱动,确认
jobs表引擎是 InnoDB,且failed_jobs表存在且可写
最麻烦的其实是环境差异:本地开发用 --daemon 没问题,但上生产用 Supervisor 管理时,必须关掉 --daemon 改用 --once,否则进程模型冲突。这点文档不提,但踩过的人基本都重装过两次 PHP。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










