mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-02 04:37:42 +08:00
Updated configuration and DI guides Russian translation [skip ci]
This commit is contained in:
@ -135,6 +135,29 @@ $config = [
|
||||
За более подробной документацией о настройках свойства `components` в конфигурации приложения обратитесь к главам
|
||||
[приложения](structure-applications.md) и [Service Locator](concept-service-locator.md).
|
||||
|
||||
Начиная с версии 2.0.11, можно настраивать [контейнер зависимостей](concept-di-container.md) через конфигурацию
|
||||
приложения. Для этого используется свойство `container`:
|
||||
|
||||
```php
|
||||
$config = [
|
||||
'id' => 'basic',
|
||||
'basePath' => dirname(__DIR__),
|
||||
'extensions' => require(__DIR__ . '/../vendor/yiisoft/extensions.php'),
|
||||
'container' => [
|
||||
'definitions' => [
|
||||
'yii\widgets\LinkPager' => ['maxButtonCount' => 5]
|
||||
],
|
||||
'singletons' => [
|
||||
// Конфигурация для единожды создающихся объектов
|
||||
]
|
||||
]
|
||||
];
|
||||
```
|
||||
|
||||
Чтобы узнать о возможных значениях `definitions` и `singletons`, а также о реальных примерах использования,
|
||||
прочитайте подраздел [более сложное практическое применение](concept-di-container.md#advanced-practical-usage) раздела
|
||||
[Dependency Injection Container](concept-di-container.md).
|
||||
|
||||
|
||||
### Конфигурации виджетов <span id="widget-configurations"></span>
|
||||
|
||||
|
||||
@ -104,6 +104,138 @@ $container->get('Foo', [], [
|
||||
> Info: Метод [[yii\di\Container::get()]] третьим аргументом принимает массив конфигурации, которым инициализируется создаваемый объект. Если класс реализует интерфейс [[yii\base\Configurable]] (например, [[yii\base\Object]]), то массив конфигурации передается в последний параметр конструктора класса. Иначе конфигурация применяется уже *после* создания объекта.
|
||||
|
||||
|
||||
Более сложное практическое применение <span id="advanced-practical-usage"></span>
|
||||
---------------
|
||||
|
||||
Допустим, мы работаем над API и у нас есть:
|
||||
|
||||
- `app\components\Request`, наследуемый от `yii\web\Request` и реализующий дополнительные возможности.
|
||||
- `app\components\Response`, наследуемый от `yii\web\Response` с свойством `format`, по умолчанию инициализируемом как `json`.
|
||||
- `app\storage\FileStorage` и `app\storage\DocumentsReader`, где реализована некая логика для работы с документами в
|
||||
неком файловом хранилище:
|
||||
|
||||
```php
|
||||
class FileStorage
|
||||
{
|
||||
public function __contruct($root) {
|
||||
// делаем что-то
|
||||
}
|
||||
}
|
||||
|
||||
class DocumentsReader
|
||||
{
|
||||
public function __contruct(FileStorage $fs) {
|
||||
// делаем что-то
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Возможно настроить несколько компонентов сразу передав массив конфигурации в метод
|
||||
[[yii\di\Container::setDefinitions()|setDefinitions()]] или [[yii\di\Container::setSingletons()|setSingletons()]].
|
||||
Внутри метода фреймворк обойдёт массив конфигурации и вызовет для каждого элемента [[yii\di\Container::set()|set()]] или
|
||||
[[yii\di\Container::setSingleton()|setSingleton()]] соответственно.
|
||||
|
||||
Формат массива конфигурации следующий:
|
||||
|
||||
- Ключ: имя класса, интерфейса или псевдонима. Ключ передаётся в первый аргумент `$class` метода
|
||||
[[yii\di\Container::set()|set()]].
|
||||
- Значение: конфигурация для класса. Возможные значения описаны в документации параметра `$definition` метода
|
||||
[[yii\di\Container::set()|set()]]. Значение передаётся в аргумент `$definition` метода [[set()]].
|
||||
|
||||
Для примера, давайте настроим наш контейнер:
|
||||
|
||||
```php
|
||||
$container->setDefinitions([
|
||||
'yii\web\Request' => 'app\components\Request',
|
||||
'yii\web\Response' => [
|
||||
'class' => 'app\components\Response',
|
||||
'format' => 'json'
|
||||
],
|
||||
'app\storage\DocumentsReader' => function () {
|
||||
$fs = new app\storage\FileStorage('/var/tempfiles');
|
||||
return new app\storage\DocumentsReader($fs);
|
||||
}
|
||||
]);
|
||||
|
||||
$reader = $container->get('app\storage\DocumentsReader);
|
||||
// Создаст объект DocumentReader со всеми зависимостями
|
||||
```
|
||||
|
||||
> Tip: Начиная с версии 2.0.11 контейнер может быть настроен в декларативном стиле через конфигурацию приложения.
|
||||
Как это сделать ищите в подразделе [Конфигурация приложения](concept-service-locator.md#application-configurations)
|
||||
раздела [Конфигурации](concept-configurations.md).
|
||||
|
||||
Вроде всё работает, но если нам необходимо создать экземпляр класса `DocumentWriter`, придётся скопировать код,
|
||||
создающий экземпляр`FileStorage`, что, очевидно, не является оптимальным.
|
||||
|
||||
Как описано в подразделе [Разрешение зависимостей](#resolving-dependencies), [[yii\di\Container::set()|set()]]
|
||||
и [[yii\di\Container::setSingleton()|setSingleton()]] могут опционально принимать третьим аргументов параметры
|
||||
для конструктора. Формат таков:
|
||||
|
||||
- Ключ: имя класса, интерфейса или псевдонима. Ключ передаётся в первый аргумент `$class` метода [[yii\di\Container::set()|set()]].
|
||||
- Значение: массив из двух элементов. Первый элемент передаётся в метод [[yii\di\Container::set()|set()]] вторым
|
||||
аргументом `$definition`, второй элемент — аргументом `$params`.
|
||||
|
||||
Исправим наш пример:
|
||||
|
||||
```php
|
||||
$container->setDefinitions([
|
||||
'tempFileStorage' => [ // для удобства мы задали псевдоним
|
||||
['class' => 'app\storage\FileStorage'],
|
||||
['/var/tempfiles']
|
||||
],
|
||||
'app\storage\DocumentsReader' => [
|
||||
['class' => 'app\storage\DocumentsReader'],
|
||||
[Instance::of('tempFileStorage')]
|
||||
],
|
||||
'app\storage\DocumentsWriter' => [
|
||||
['class' => 'app\storage\DocumentsWriter'],
|
||||
[Instance::of('tempFileStorage')]
|
||||
]
|
||||
]);
|
||||
|
||||
$reader = $container->get('app\storage\DocumentsReader);
|
||||
// Код будет работать ровно так же, как и в предыдущем примере.
|
||||
```
|
||||
|
||||
Вы могли заметить вызов `Instance::of('tempFileStorage')`. Он означает, что [[yii\di\Container|Container]]
|
||||
наявно предоставит зависимость, зарегистрированную с именем `tempFileStorage` и передаст её первым аргументом
|
||||
в конструктор `app\storage\DocumentsWriter`.
|
||||
|
||||
> Note: Методы [[yii\di\Container::setDefinitions()|setDefinitions()]] и [[yii\di\Container::setSingletons()|setSingletons()]]
|
||||
доступны с версии 2.0.11.
|
||||
|
||||
Ещё один шаг по оптимизации конфигурации — регистрировать некоторые зависимости как синглтоны. Зависимость, регистрируемая
|
||||
через метод [[yii\di\Container::set()|set()]] будет созаваться каждый раз при обращении к ней. Некоторые классы не меняют
|
||||
своего состояния на протяжении всей работы приложения, поэтому могут быть зарегистрированы как синглтоны. Это увеличит
|
||||
производительность приложения.
|
||||
|
||||
Хорошим примером может быть класс `app\storage\FileStorage`, который выполняет некие операции над файловой системой
|
||||
через простой API: `$fs->read()`, `$fs->write()`. Обе операции не меняют внутреннее состояние класса, поэтому мы можем
|
||||
создать класс один раз и далее использовать его.
|
||||
|
||||
```php
|
||||
$container->setSingletons([
|
||||
'tempFileStorage' => [
|
||||
['class' => 'app\storage\FileStorage'],
|
||||
['/var/tempfiles']
|
||||
],
|
||||
]);
|
||||
|
||||
$container->setDefinitions([
|
||||
'app\storage\DocumentsReader' => [
|
||||
['class' => 'app\storage\DocumentsReader'],
|
||||
[Instance::of('tempFileStorage')]
|
||||
],
|
||||
'app\storage\DocumentsWriter' => [
|
||||
['class' => 'app\storage\DocumentsWriter'],
|
||||
[Instance::of('tempFileStorage')]
|
||||
]
|
||||
]);
|
||||
|
||||
$reader = $container->get('app\storage\DocumentsReader);
|
||||
```
|
||||
|
||||
### Внедрение зависимости через PHP callback <span id="php-callable-injection"></span>
|
||||
|
||||
В данном случае, контейнер будет использовать зарегистрированный PHP callback для создания новых экземпляров класса.
|
||||
@ -211,13 +343,16 @@ $container->setSingleton('yii\db\Connection', [
|
||||
Разрешение зависимостей <span id="resolving-dependencies"></span>
|
||||
----------------------
|
||||
После регистрации зависимостей, вы можете использовать контейнер внедрения зависимостей для создания новых объектов,
|
||||
и контейнер автоматически разрешит зависимости их экземпляра и их внедрений во вновь создаваемых объектах. Разрешение зависимостей рекурсивно, то есть
|
||||
если зависимость имеет другие зависимости, эти зависимости также будут автоматически разрешены.
|
||||
и контейнер автоматически разрешит зависимости их экземпляра и их внедрений во вновь создаваемых объектах. Разрешение
|
||||
зависимостей рекурсивно, то есть если зависимость имеет другие зависимости, эти зависимости также будут автоматически
|
||||
разрешены.
|
||||
|
||||
Вы можете использовать [[yii\di\Container::get()]] для создания новых объектов. Метод принимает имя зависимости, которым может быть имя класса, имя интерфейса или псевдоним.
|
||||
Имя зависимости может быть или не может быть зарегистрировано через `set()` или `setSingleton()`.
|
||||
Вы можете опционально предоставить список параметров конструктора класса и [конфигурацию](concept-configurations.md) для настройки созданного объекта.
|
||||
Например,
|
||||
Вы можете использовать [[yii\di\Container::get()]] для создания или получения объектов. Метод принимает имя зависимости,
|
||||
которым может быть имя класса, имя интерфейса или псевдоним. Имя зависимости может быть зарегистрировано через
|
||||
`set()` или `setSingleton()`. Вы можете опционально предоставить список параметров конструктора класса и
|
||||
[конфигурацию](concept-configurations.md) для настройки созданного объекта.
|
||||
|
||||
Например:
|
||||
|
||||
```php
|
||||
// "db" ранее зарегистрированный псевдоним
|
||||
@ -228,11 +363,14 @@ $engine = $container->get('app\components\SearchEngine', [$apiKey], ['type' => 1
|
||||
```
|
||||
|
||||
За кулисами, контейнер внедрения зависимостей делает гораздо больше работы, чем просто создание нового объекта.
|
||||
Прежде всего, контейнер, осмотрит конструктор класса, чтобы узнать имя зависимого класса или интерфейса, а затем автоматически разрешит эти зависимости рекурсивно.
|
||||
Прежде всего, контейнер, осмотрит конструктор класса, чтобы узнать имя зависимого класса или интерфейса, а затем
|
||||
автоматически разрешит эти зависимости рекурсивно.
|
||||
|
||||
Следующий код демонстрирует более сложный пример. Класс `UserLister` зависит от объекта, реализующего интерфейс `UserFinderInterface`; класс `UserFinder` реализует этот интерфейс и зависит от
|
||||
объекта `Connection`. Все эти зависимости были объявлены через тип подсказки параметров конструктора класса.
|
||||
При регистрации зависимости через свойство, контейнер внедрения зависимостей позволяет автоматически разрешить эти зависимости и создаёт новый экземпляр `UserLister` простым вызовом `get('userLister')`.
|
||||
Следующий код демонстрирует более сложный пример. Класс `UserLister` зависит от объекта, реализующего интерфейс
|
||||
`UserFinderInterface`; класс `UserFinder` реализует этот интерфейс и зависит от объекта `Connection`. Все эти зависимости
|
||||
были объявлены через тип подсказки параметров конструктора класса. При регистрации зависимости через свойство, контейнер
|
||||
внедрения зависимостей позволяет автоматически разрешить эти зависимости и создаёт новый экземпляр `UserLister` простым
|
||||
вызовом `get('userLister')`.
|
||||
|
||||
```php
|
||||
namespace app\models;
|
||||
@ -291,17 +429,17 @@ $lister = new UserLister($finder);
|
||||
```
|
||||
|
||||
|
||||
Практическое использование <span id="practical-usage"></span>
|
||||
Практическое применение <span id="practical-usage"></span>
|
||||
---------------
|
||||
|
||||
Yii создаёт контейнер внедрения зависимостей когда вы подключаете файл `Yii.php` во [входном скрипте](structure-entry-scripts.md)
|
||||
вашего приложения. Контейнер внедрения зависимостей доступен через [[Yii::$container]]. При вызове [[Yii::createObject()]],
|
||||
метод на самом деле вызовет метод контейнера [[yii\di\Container::get()|get()]], чтобы создать новый объект.
|
||||
Как упомянуто выше, контейнер внедрения зависимостей автоматически разрешит зависимости (если таковые имеются) и внедрит их в только что созданный объект.
|
||||
Поскольку Yii использует [[Yii::createObject()]] в большей части кода своего ядра для создания новых объектов, это означает,
|
||||
что вы можете настроить глобальные объекты, имея дело с [[Yii::$container]].
|
||||
Как упомянуто выше, контейнер внедрения зависимостей автоматически разрешит зависимости (если таковые имеются) и внедрит их
|
||||
получаемый объект. Поскольку Yii использует [[Yii::createObject()]] в большей части кода своего ядра для создания новых
|
||||
объектов, это означает, что вы можете настроить глобальные объекты, имея дело с [[Yii::$container]].
|
||||
|
||||
Например, вы можете настроить по умолчанию глобальное количество кнопок в пейджере [[yii\widgets\LinkPager]]:
|
||||
Например, давайте настроим количество кнопок в пейджере [[yii\widgets\LinkPager]] по умолчанию глобально:
|
||||
|
||||
```php
|
||||
\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);
|
||||
@ -356,8 +494,11 @@ class HotelController extends Controller
|
||||
Поскольку зависимости необходимы тогда, когда создаются новые объекты, то их регистрация должна быть сделана
|
||||
как можно раньше. Ниже приведены рекомендуемые практики:
|
||||
|
||||
* Если вы разработчик приложения, то вы можете зарегистрировать зависимости во [входном скрипте](structure-entry-scripts.md) вашего приложения или в скрипте, подключённого во входном скрипте.
|
||||
* Если вы разработчик распространяемого [расширения](structure-extensions.md), то вы можете зарегистрировать зависимости в загрузочном классе расширения.
|
||||
* Если вы разработчик приложения, то вы можете зарегистрировать зависимости в конфигурации вашего приложения.
|
||||
Как это сделать описано в подразделе [Конфигурация приложения](concept-service-locator.md#application-configurations)
|
||||
раздела [Конфигурации](concept-configurations.md).
|
||||
* Если вы разработчик распространяемого [расширения](structure-extensions.md), то вы можете зарегистрировать зависимости
|
||||
в загрузочном классе расширения.
|
||||
|
||||
|
||||
Итог <span id="summary"></span>
|
||||
|
||||
Reference in New Issue
Block a user