thamtech / yii2-di
Yii2 依赖注入增强
Requires
- php: >=5.6.0
- yiisoft/yii2: >=2.0.14 <2.1
Requires (Dev)
- phpunit/phpunit: ^4.1 || ^5.0
This package is auto-updated.
Last update: 2024-09-10 04:45:24 UTC
README
Yii2-di 为 Yii2 的依赖注入框架提供了一些增强功能。
安装
安装此扩展的首选方式是通过 composer。
php composer.phar require --prefer-dist thamtech/yii2-di
或者添加
"thamtech/yii2-di": "*"
到你的 composer.json
文件的 require
部分。
使用
实例
Instance::ensureAny()
方法可以用于替代 Instance::ensure(),如果你想要确保一个对象是任何指定类型之一。
例如,
use yii\db\Connection; // returns Yii::$app->db $db = \thamtech\di\Instance::ensure('db', [ Connection::class, \yii\redis\Connection::class, ]); // returns an instance of Connection using the given configuration. // * the first type listed is used as the 'class' parameter when it isn't // specified in the reference array $db = \thamtech\di\Instance::ensureAny([ 'dsn' => 'sqlite:path/to/my.db' ], [ Connection::class, \yii\redis\Connection::class, ])
实例提供者
InstanceProvider
类增加了在依赖注入实现中使用提供者的支持。这可以用于多个目的,例如延迟或可选地检索实例,或者作为某些实例类型的标记。
延迟/可选检索
你可能想要将一个对象注入到一个类中,但这个类可能还不需要(或者永远不需要)实例化这个对象。在这种情况下,你可以注入一个提供者,并让你的类决定何时以及是否要调用 get()
方法来获取对象实例。
例如,
class ExpensiveInstanceProvider implements \thamtech\di\Provider { public function get() { // instantiate $object // ... return $objectInstance; } } class DependendClass { private $provider; public function __construct(ExpensiveInstanceProvider $provider) { $this->provider = $provider; } public function fooBar() { $objectInstance = $provider->get(); } }
提供者作为标记类
Java 开发者可能会使用在抽象类型参数上使用注解来指定实例的特定版本。
例如,
class FooCacheUtil { private Cache cache; // dependency injection provides the '@foo' cache component public FooCache(@foo Cache cache) { this.cache = cache; } } class BarCacheUtil { private Cache cache; // dependency injection provides the @bar' cache component public BarCache(@bar Cache cache) { this.cache = cache; } }
要使用 Yii 的依赖注入实现类似的功能,你可以创建 InstanceProvider
的标记类实现,并在依赖注入容器中定义你的标记组件。
例如,
namespace example\package; class FooCacheProvider extends \thamtech\di\InstanceProvider {} class BarCacheProvider extends \thamtech\di\InstanceProvider {} class FooCacheUtil { private $cache; // dependency injection provides a FooCacheProvider public function __construct(FooCacheProvider $cacheProvider) { $this->cache = $cacheProvider->get(); } } class BarCacheUtil { private $cache; // dependency injection provides a BarCacheProvider public function __construct(BarCacheProvider $cacheProvider) { $this->cache = $cacheProvider->get(); } } // application's container configuration 'container' => [ 'singletons' => [ 'example\package\FooCache:::provided' => [ 'class' => 'yii\caching\ArrayCache', ], 'example\package\BarCache:::provided' => [ 'class' => 'yii\caching\DbCache', ], ], ],
在上面的示例中,FooCacheProvider
和 BarCacheProvider
是 InstanceProvider
的子类,它们被用作标记类,指示通过依赖注入提供哪种类型的缓存组件。
InstanceProvider
的默认实现将查找容器中定义的具有与子类提供者类名相对应名称的实例。删除 Provider
后缀,并附加一个 :::provided
后缀。
所以 example\package\FooCacheProvider
的 get()
方法将使用容器查找定义为 example\package\FooCache:::provided
的实例。
当你实现你的 InstanceProvider
子类时,可以通过覆盖一个或多个 $class
、$params
和 $config
属性来覆盖此行为。
例如,
namespace example\package; class FooCacheProvider extends \thamtech\di\InstanceProvider { public $class = 'yii\caching\ArrayCache'; public $config = [ 'serializer' => false, 'defaultDuration' => 3600, ]; }
类型安全
如上所述,你可以通过覆盖类属性或通过容器定义来配置提供者以返回任何类型的对象。你可能想要强制执行一定级别的类型安全。
例如,如果 FooCacheProvider
应该只返回某些缓存类型,你可以这样指定
namespace example\package; class FooCacheProvider extends \thamtech\di\InstanceProvider { public $ensureTypes = [ 'yii\caching\ArrayCache', 'yii\caching\FileCache', ]; }
这将确保如果有人意外地配置它返回其他内容,你的应用程序将抛出异常
'container' => [ 'singletons' => [ 'example\package\FooCache:::provided' => [ 'class' => 'yii\caching\DbCache', ], ], ], $fooCacheProvider = new FooCacheProvider(); $fooCacheProvider->get(); // will throw an InvalidConfigException