yii 3.0 默认以 di 容器为核心,自动解析依赖并支持构造注入;yii 2.0 以服务定位器为主,di 需手动启用且不支持自动构造注入,组件须显式注册并手动传参。

Yii 2.0 和 Yii 3.0 的依赖注入(DI)机制差异显著,不能混用或套用同一套写法。核心区别在于:Yii 2.0 默认不启用 DI 容器接管对象创建,而 Yii 3.0 将 DI 容器作为应用启动和对象解析的**默认中枢**。
Yii 2.0:服务定位器为主,DI 容器需手动介入
Yii 2.0 中 Yii::$app 是服务定位器(Service Locator),不是 DI 容器。它只认你显式注册在 components 配置里的组件,且不解析构造函数参数。
- 要让自定义类(如
OrderService)被Yii::$app->get('orderService')找到,必须在config/web.php的components数组里声明:'orderService' => ['class' => 'app\services\OrderService'] - 若该类构造函数需要
DbConnection和CacheInterface,服务定位器不会自动提供——你得手动补全:'orderService' => ['class' => 'app\services\OrderService', 'db' => Yii::$app->db, 'cache' => Yii::$app->cache] - 真要用自动构造注入,得单独实例化
yii\di\Container:$container = new \yii\di\Container();<br>$container->set('app\interfaces\OrderInterface', 'app\services\OrderService');<br>$service = $container->get('app\interfaces\OrderInterface'); - 控制器不支持构造函数注入,因为框架用
new $class()创建;需通过自定义基类 + 容器配置(__construct()参数列表显式声明)来绕过限制
Yii 3.0:DI 容器是默认引擎,服务定位器退居辅助
Yii 3.0 彻底转向以 yii\di\Container 为核心。应用启动时即初始化全局容器,所有对象(包括控制器、中间件、命令)都由容器创建并自动解析依赖。
- 无需在配置中预先注册每个组件;只要类已存在、类型提示清晰,容器就能自动构造:
class UserController { public function __construct(private UserService $userService) {} }
框架会自动注入UserService实例 - 接口绑定直接在应用启动时完成(如
config/common.php):'container' => [ 'definitions' => [ UserInterface::class => DbUserRepository::class ] ] - 控制器、命令、中间件等均支持构造注入,不再需要基类封装或手动传参
- 服务定位器(
Yii::$app)仍存在,但主要用作快捷访问已注册的“核心服务”(如db,cache),不再是依赖管理主干
跨版本迁移关键提醒
从 Yii 2.0 升级到 3.0 时,以下习惯必须调整:
- 删掉
components中大量手工配置的 service 类——改用容器定义或自动发现 - 把原来写在
init()或beforeAction()里的依赖赋值逻辑,移到构造函数中 - 避免在业务类中调用
Yii::$app->get()获取服务;优先用构造注入,保证可测试性 - 注意
yii\di\Container在 3.0 中支持作用域(scoped)、工厂回调、条件绑定等高级特性,2.0 版本功能较弱
不复杂但容易忽略:版本决定架构思路。2.0 是“注册后查找”,3.0 是“声明即可用”。











