服务定位器是一个知道如何提供应用程序可能需要的所有种类的服务(或组件)的对象。在服务定位器中,每个组件仅存在一个实例,由一个唯一的 ID 标识。您可以使用该 ID 从服务定位器中检索组件。
在 Yii 中,服务定位器只是一个 yii\di\ServiceLocator 实例或子类。
Yii 中最常用的服务定位器是应用程序对象,可以通过 \Yii::$app
访问。它提供的服务称为应用程序组件,例如 request
、response
和 urlManager
组件。您可以轻松地通过服务定位器提供的功能来配置这些组件,甚至用您自己的实现替换它们。
除了应用程序对象之外,每个模块对象也是一个服务定位器。模块实现了 树遍历。
要使用服务定位器,第一步是将组件注册到它。可以通过 yii\di\ServiceLocator::set() 注册组件。以下代码展示了注册组件的不同方法
use yii\di\ServiceLocator;
use yii\caching\FileCache;
$locator = new ServiceLocator;
// register "cache" using a class name that can be used to create a component
$locator->set('cache', 'yii\caching\ApcCache');
// register "db" using a configuration array that can be used to create a component
$locator->set('db', [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=demo',
'username' => 'root',
'password' => '',
]);
// register "search" using an anonymous function that builds a component
$locator->set('search', function () {
return new app\components\SolrService;
});
// register "pageCache" using a component
$locator->set('pageCache', new FileCache);
一旦组件被注册,就可以使用它的 ID 以以下两种方式之一访问它
$cache = $locator->get('cache');
// or alternatively
$cache = $locator->cache;
如上所示,yii\di\ServiceLocator 允许您像使用属性一样使用组件 ID 访问组件。当您第一次访问组件时,yii\di\ServiceLocator 将使用组件注册信息创建一个新组件实例并将其返回。稍后,如果再次访问该组件,服务定位器将返回同一个实例。
您可以使用 yii\di\ServiceLocator::has() 检查组件 ID 是否已经注册。如果您使用无效的 ID 调用 yii\di\ServiceLocator::get(),则会抛出异常。
因为服务定位器通常是使用 配置 创建的,所以提供了一个名为 components 的可写属性。这允许您一次配置和注册多个组件。以下代码展示了一个配置数组,可用于使用 db
、cache
、tz
和 search
组件配置服务定位器(例如 应用程序)
return [
// ...
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=demo',
'username' => 'root',
'password' => '',
],
'cache' => 'yii\caching\ApcCache',
'tz' => function() {
return new \DateTimeZone(Yii::$app->formatter->defaultTimeZone);
},
'search' => function () {
$solr = new app\components\SolrService('127.0.0.1');
// ... other initializations ...
return $solr;
},
],
];
在上面,有一种配置 search
组件的替代方法。与其直接编写一个构建 SolrService
实例的 PHP 回调,不如使用一个静态类方法来返回这样的回调,如下所示
class SolrServiceBuilder
{
public static function build($ip)
{
return function () use ($ip) {
$solr = new app\components\SolrService($ip);
// ... other initializations ...
return $solr;
};
}
}
return [
// ...
'components' => [
// ...
'search' => SolrServiceBuilder::build('127.0.0.1'),
],
];
当您发布封装了一些非 Yii 第三方库的 Yii 组件时,这种替代方法是最可取的。您使用上面所示的静态方法来表示构建第三方对象的复杂逻辑,而您的组件的用户只需要调用静态方法来配置该组件。
模块允许任意嵌套;Yii 应用程序本质上是模块的树。由于这些模块中的每一个都是一个服务定位器,因此子模块有权访问其父模块是有意义的。这允许模块使用 $this->get('db')
而不是引用根服务定位器 Yii::$app->get('db')
。额外的好处是开发人员可以选择在模块中覆盖配置。
如果模块无法满足从模块检索服务的请求,该请求将传递给其父级。
请注意,模块中组件的配置永远不会与父模块中组件的配置合并。服务定位器模式允许我们定义命名服务,但不能假设具有相同名称的服务使用相同的配置参数。
发现错别字或您认为此页面需要改进?
在github上编辑 !
注册 或 登录 发表评论。