basic-service-locator.md 3.75 KB
Newer Older
Qiang Xue committed
1 2 3 4
Service Locator
===============

> Note: This chapter needs cleanup.
Qiang Xue committed
5

6
Both service locator and dependency injection are popular design patterns that allow building software
Qiang Xue committed
7 8
in a loosely-coupled fashion. Yii uses service locator and dependency injection extensively,
even though you may not be aware of them. In this tutorial, we will explore their implementation
9 10 11
and support to help you write code more consciously. We also highly recommend you to read
[Martin's article](http://martinfowler.com/articles/injection.html) to get a deeper understanding of
service locator and dependency injection.
Qiang Xue committed
12

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
A service locator is an object that knows how to provide all sorts of services (or components) that an application
might need. Within a service locator, each component has only a single instance which is uniquely identified by an ID.
You use the ID to retrieve a component from the service locator. In Yii, a service locator is simply an instance 
of [[yii\di\ServiceLocator]] or its child class.

The most commonly used service locator in Yii is the *application* object which can be accessed through
`\Yii::$app`. The services it provides are called *application components*, such as `request`, `response`,
`urlManager`. You may configure these components or replace them with your own implementations easily
through functionality provided the service locator.

Besides the application object, each module object is also a service locator.

To use a service locator, the first step is to register components. A component can be registered
via [[yii\di\ServiceLocator::set()]]. The following code shows different ways of registering components:

```php
$locator = new \yii\di\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 "db" using an anonymous function that builds a component
$locator->set('search', function () {
    return new app\components\SolrService;
});
```

Once a component is registered, you can access it using its ID in one of the following two ways:
Qiang Xue committed
49 50

```php
51
$cache = $locator->get('cache');
Qiang Xue committed
52
// or alternatively
53
$cache = $locator->cache;
Qiang Xue committed
54 55
```

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
As shown above, [[yii\di\ServiceLocator]] allows you to access a component like a property using the component ID.
When you access a component for the first time, [[yii\di\ServiceLocator]] will use the component registration
information to create a new instance of the component and return it. Later if the component is accessed again,
the service locator will return the same instance.

You may use [[yii\di\ServiceLocator::has()]] to check if a component ID has already been registered.
If you call [[yii\di\ServiceLocator::get()]] with an invalid ID, an exception will be thrown.


Because service locators are often being configured using configuration arrays, a method named
[[yii\di\ServiceLocator::setComponents()]] is provided to allow registering components in configuration arrays.
The method is a setter which defines a writable property `components` that can be configured.
The following code shows a configuration array that can be used to configure an application and register
the "db", "cache" and "search" components:

```php
return [
    // ...
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=demo',
            'username' => 'root',
            'password' => '',
        ],
        'cache' => 'yii\caching\ApcCache',
        'search' => function () {
            return new app\components\SolrService;
        },
    ],
];
```