直接php script.php报Call to a member function on null,因裸脚本跳过Webman启动流程,DI容器、配置、数据库等未初始化;必须用./webman make:command生成命令类,在execute()中直接调用config()、Db::table()等。

为什么直接 php script.php 会报 Call to a member function on null
因为裸跑 PHP 脚本完全跳过了 Webman 的启动流程,support/bootstrap.php 没执行,DI 容器、配置加载、数据库连接器全为空。哪怕你手动 require_once 了 autoload 和 bootstrap,也大概率失败——bootstrap.php 依赖 start.php 注入的上下文(比如 define('WEBMAN_START', true) 和容器初始化顺序),CLI 直接运行时这些根本不存在。
典型现象包括:
-
config('database')返回null -
Db::table('user')报Call to a member function table() on null -
Log::info()静默丢弃日志,不写入文件 -
Container::get('logger')报Call to a member function get() on null
如何用 ./webman make:command 创建可用命令
这是唯一被框架支持的路径。执行命令生成骨架类后,execute() 方法内可直接使用全部框架能力,无需任何手动初始化。
- 运行
./webman make:command db:backup→ 生成app/command/DbBackupCommand.php - 类必须继承
Symfony\Component\Console\Command\Command -
protected static $defaultName必须是字符串字面量,例如'db:backup',不能拼接、不能变量赋值,否则./webman list不识别 - 命名空间必须为
app\command(注意反斜杠),文件名需与类名严格一致(如DbBackupCommand) -
configure()和execute()方法不可省略:configure()中至少调用一次$this->addArgument()或$this->addOption();execute()返回值必须是int(self::SUCCESS或self::FAILURE)
参数获取和框架服务调用怎么写
别碰 $argv,也别自己解析命令行参数。Symfony Console 已提供结构化支持,且框架已注入完整上下文。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
- 定义参数:
$this->addArgument('table', InputArgument::REQUIRED, '表名') - 定义选项:
$this->addOption('limit', 'l', InputOption::VALUE_REQUIRED, '限制条数', 100) - 获取参数:
$input->getArgument('table') - 获取选项:
$input->getOption('limit') - 配置读取:
config('database.connections.mysql.host') - 数据库操作:
Db::table('users')->where('id', '>', 100)->get() - 日志写入:
Log::info('backup started', ['table' => $table])
命令不显示在 ./webman list 中怎么办
即使类存在、语法正确,命令也可能“隐身”。排查顺序要严格按路径、命名、注册三步走:
- 确认文件路径是
app/command/xxx.php(不是app/commands/、app/console/或其他) - 检查命名空间是否为
app\command,类名首字母大写且与文件名完全一致 - 确保
$defaultName是硬编码字符串,且不含非法字符(如空格、中文、特殊符号) - 运行
composer dump-autoload确保自动加载生效(尤其改过命名空间或类名后) - 不要删掉
configure()方法体——哪怕只写$this->addArgument('dummy', InputArgument::OPTIONAL);也能绕过 Symfony 的“未配置”判定
最常被忽略的是 configure() 方法的存在性,以及 $defaultName 的字面量要求——这两点不满足,命令就等于没注册。










