webman默认关闭自动依赖注入,因反射开销与类结构隐式约束不符其高性能轻量定位;启用需配置php-di容器并开启useautowiring(true)和useattributes(true),否则仅支持手动app()->get()。

Webman 默认不启用自动依赖注入,必须手动配置容器(如 php-di)才能使用构造函数自动注入、属性注入等功能。 否则所有服务都得 app()->get(Service::class) 手动取,无法享受框架级解耦和测试便利性。
webman 为什么默认关闭自动 DI?
因为自动注入会带来运行时反射开销,且对类结构有隐式要求(比如构造函数参数必须可解析)。webman 定位是高性能轻量框架,不希望默认为所有用户承担这部分成本和约束。
- 未开启时,
container.php返回的是一个仅支持基本set()/get()的简易容器,不解析类型提示 - 开启后,容器需扫描类、读取 PHPDoc 或 PHP 8+ 属性/构造函数类型,再递归解析依赖树
- 若项目里大量使用匿名类、动态构造参数或魔术方法,自动注入可能失败且报错晦涩(比如
Entry "App\Service\X" cannot be resolved)
如何启用 php-di 实现自动注入?
关键不是装包,而是让 config/container.php 返回一个真正能干活的 PSR-11 容器实例。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
- 执行
composer require php-di/php-di:^7.0 - 确保
config/container.php内容最终形如:
$builder = new \DI\ContainerBuilder();
$builder->addDefinitions(config('dependence', []));
$builder->useAutowiring(true);
$builder->useAttributes(true);
return $builder->build();
-
useAutowiring(true)开启基于类型提示的自动构造;useAttributes(true)支持#[Inject]注解(PHP 8+) -
config('dependence', [])对应config/dependence.php,用于显式绑定接口到实现,例如:ServiceInterface::class => Service::class
常见注入失败原因与排查点
注入报错往往不是代码写错了,而是容器没“看见”该类或路径没扫进去。
- 类没被自动加载:确认
composer.json的autoload包含对应命名空间,且已运行composer dump-autoload - 构造函数含不可解析参数:比如
public function __construct(array $config)—— 容器不知道该传什么数组,必须在dependence.php中定义该参数键名 - 循环依赖:A 依赖 B,B 又依赖 A;php-di 默认不支持,会抛出
Circular dependency detected - 单例 vs 瞬态混淆:webman 的
app()->get()每次都返回新实例,而 php-di 默认是 singleton;若业务需要每次新建,得显式声明Scope::PROTOTYPE
webman 容器与 Laravel/Symfony 的关键差异
别套用其他框架经验——webman 的容器更“薄”,不内置服务注册表或启动生命周期钩子。
- 没有
AppServiceProvider这类自动加载的服务提供者,所有绑定必须写死在dependence.php或container.php中 - 不支持
bindIf()或条件绑定;想按环境切换实现,得手动写if (env('APP_ENV') === 'test') { ... } - 容器本身不参与 HTTP 生命周期管理,比如 request-scoped 服务需自行用
onRequest事件 +set()绑定,框架不代劳
最易被忽略的一点:webman 的容器只在「应用启动时」构建一次,后续修改 dependence.php 不会热更新,必须重启 worker 进程才生效。开发中改了绑定却没效果,大概率是忘了 php webman restart。










