在 composer.json 的 scripts 段定义 ThinkPHP 脚本需确保类可自动加载(如 "AppConsole::clearRuntime"),调用前须执行 composer dump-autoload;优先用 composer run 而非 php think,因其自动加载 vendor/autoload.php 并支持完整依赖环境。

ThinkPHP 项目里直接写 composer.json 的 scripts 段,就能让 Composer 执行自定义命令——不是用 shell 脚本包装,也不是靠手动运行 PHP 文件,而是原生支持、自动加载、可复用的执行入口。
怎么在 composer.json 里定义 ThinkPHP 相关脚本
ThinkPHP 本身不接管 scripts,但它的自动加载和命令行环境完全兼容。你只需把逻辑封装成可调用的 PHP 函数或类方法,再在 scripts 中指向它即可。
- 脚本必须是可执行的 PHP callable:可以是闭包(需写在
autoload-dev下)、静态方法(如"App\Console::clearCache"),或带__invoke的类 - 路径必须能被 Composer 自动加载:确保对应类在
autoload或autoload-dev的 PSR-4 映射范围内,比如"App\Console\": "app/console/" - 不要用相对路径或
require_once手动引入:Composer 运行时不会 cd 到项目根目录以外,但也不会自动包含未声明的文件 - 示例写法(加到项目根目录
composer.json的scripts字段):"scripts": { "tp:clear": "App\Console::clearRuntime", "tp:build": [ "@tp:clear", "php think build" ] }
composer run 和传统 php think 的区别
从 Composer 2.2 开始,composer run(或简写 composer run-script)才是标准方式;composer script 已废弃。它和直接运行 php think 的核心差异在于执行上下文和依赖隔离:
-
composer run tp:clear会先加载vendor/autoload.php,再调用目标方法,所有依赖类(包括 ThinkPHP 核心类)都可用 -
php think clear:runtime是 ThinkPHP 自己的命令行入口,走的是框架自己的调度逻辑,可能绕过某些 Composer 初始化步骤(如autoload-dev中的测试类) - 如果你的脚本要操作
config/或读取.env,优先用composer run,因为 ThinkPHP 的think命令在未初始化应用实例前可能无法正确解析配置 - 注意环境变量:Composer 脚本默认不读取
.env,需在脚本内部显式调用DotenvDotenv::createImmutable(__DIR__)->load()(如果用了 vlucas/phpdotenv)
常见报错:Class not found 或 Undefined function
这类错误基本都卡在自动加载或执行时机上,不是代码写错了,而是路径或加载顺序没对齐:
立即学习“PHP免费学习笔记(深入)”;
-
Class 'AppConsole' not found:检查composer.json的autoload是否包含该命名空间,然后必须运行composer dump-autoload才生效(改了 autoload 配置后必做) -
Call to undefined function thinkacadeCache::clear():说明 Facade 类没注册,通常因为脚本没启动 ThinkPHP 应用容器——此时不能直接调用 Facade,得改用thinkContainer::getInstance()->get('cache')->clear() -
Undefined variable $app:你在脚本里直接用了控制器或中间件里才有的变量,而scripts是纯 CLI 上下文,没有请求生命周期,$app不自动存在 - Windows 下路径分隔符出问题:避免硬编码
__DIR__ . '/runtime',改用dirname(__DIR__) . DIRECTORY_SEPARATOR . 'runtime'
实际能用的 ThinkPHP 脚本场景
别只把它当“跑个命令”的快捷方式,真正省事的是那些需要组合多个动作、且和依赖强相关的任务:
- 构建发布包:
"build:dist": "rm -rf build && mkdir build && cp -r app config public think LICENSE README.md build/ && composer install --no-dev --optimize-autoloader" - 自动化迁移与种子:
"migrate:seed": ["php think migrate:run", "php think seed:run"](前提是think命令已注册为可执行) - 清理 + 重载配置:
"reload:config": ["php think clear:config", "php think optimize:config"] - CI/CD 中预检:
"ci:check": "php -l app/ && php -l config/ && composer validate --no-check-publish"
最易被忽略的一点:Composer 脚本里的每个命令都是独立进程,上一条的环境变量或全局状态不会透传给下一条。想共享数据(比如生成一个 token 供后续命令用),得写临时文件或用 export + eval 包裹整个序列——但这已经超出 Composer 设计初衷,不如拆成一个专用 PHP 脚本。



















