mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-03 13:58:55 +08:00
Updated configuration and DI guides Russian translation [skip ci]
This commit is contained in:
@ -135,6 +135,29 @@ $config = [
|
|||||||
За более подробной документацией о настройках свойства `components` в конфигурации приложения обратитесь к главам
|
За более подробной документацией о настройках свойства `components` в конфигурации приложения обратитесь к главам
|
||||||
[приложения](structure-applications.md) и [Service Locator](concept-service-locator.md).
|
[приложения](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>
|
### Конфигурации виджетов <span id="widget-configurations"></span>
|
||||||
|
|
||||||
|
|||||||
@ -104,6 +104,138 @@ $container->get('Foo', [], [
|
|||||||
> Info: Метод [[yii\di\Container::get()]] третьим аргументом принимает массив конфигурации, которым инициализируется создаваемый объект. Если класс реализует интерфейс [[yii\base\Configurable]] (например, [[yii\base\Object]]), то массив конфигурации передается в последний параметр конструктора класса. Иначе конфигурация применяется уже *после* создания объекта.
|
> 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 <span id="php-callable-injection"></span>
|
||||||
|
|
||||||
В данном случае, контейнер будет использовать зарегистрированный PHP callback для создания новых экземпляров класса.
|
В данном случае, контейнер будет использовать зарегистрированный PHP callback для создания новых экземпляров класса.
|
||||||
@ -211,13 +343,16 @@ $container->setSingleton('yii\db\Connection', [
|
|||||||
Разрешение зависимостей <span id="resolving-dependencies"></span>
|
Разрешение зависимостей <span id="resolving-dependencies"></span>
|
||||||
----------------------
|
----------------------
|
||||||
После регистрации зависимостей, вы можете использовать контейнер внедрения зависимостей для создания новых объектов,
|
После регистрации зависимостей, вы можете использовать контейнер внедрения зависимостей для создания новых объектов,
|
||||||
и контейнер автоматически разрешит зависимости их экземпляра и их внедрений во вновь создаваемых объектах. Разрешение зависимостей рекурсивно, то есть
|
и контейнер автоматически разрешит зависимости их экземпляра и их внедрений во вновь создаваемых объектах. Разрешение
|
||||||
если зависимость имеет другие зависимости, эти зависимости также будут автоматически разрешены.
|
зависимостей рекурсивно, то есть если зависимость имеет другие зависимости, эти зависимости также будут автоматически
|
||||||
|
разрешены.
|
||||||
|
|
||||||
Вы можете использовать [[yii\di\Container::get()]] для создания новых объектов. Метод принимает имя зависимости, которым может быть имя класса, имя интерфейса или псевдоним.
|
Вы можете использовать [[yii\di\Container::get()]] для создания или получения объектов. Метод принимает имя зависимости,
|
||||||
Имя зависимости может быть или не может быть зарегистрировано через `set()` или `setSingleton()`.
|
которым может быть имя класса, имя интерфейса или псевдоним. Имя зависимости может быть зарегистрировано через
|
||||||
Вы можете опционально предоставить список параметров конструктора класса и [конфигурацию](concept-configurations.md) для настройки созданного объекта.
|
`set()` или `setSingleton()`. Вы можете опционально предоставить список параметров конструктора класса и
|
||||||
Например,
|
[конфигурацию](concept-configurations.md) для настройки созданного объекта.
|
||||||
|
|
||||||
|
Например:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
// "db" ранее зарегистрированный псевдоним
|
// "db" ранее зарегистрированный псевдоним
|
||||||
@ -228,11 +363,14 @@ $engine = $container->get('app\components\SearchEngine', [$apiKey], ['type' => 1
|
|||||||
```
|
```
|
||||||
|
|
||||||
За кулисами, контейнер внедрения зависимостей делает гораздо больше работы, чем просто создание нового объекта.
|
За кулисами, контейнер внедрения зависимостей делает гораздо больше работы, чем просто создание нового объекта.
|
||||||
Прежде всего, контейнер, осмотрит конструктор класса, чтобы узнать имя зависимого класса или интерфейса, а затем автоматически разрешит эти зависимости рекурсивно.
|
Прежде всего, контейнер, осмотрит конструктор класса, чтобы узнать имя зависимого класса или интерфейса, а затем
|
||||||
|
автоматически разрешит эти зависимости рекурсивно.
|
||||||
|
|
||||||
Следующий код демонстрирует более сложный пример. Класс `UserLister` зависит от объекта, реализующего интерфейс `UserFinderInterface`; класс `UserFinder` реализует этот интерфейс и зависит от
|
Следующий код демонстрирует более сложный пример. Класс `UserLister` зависит от объекта, реализующего интерфейс
|
||||||
объекта `Connection`. Все эти зависимости были объявлены через тип подсказки параметров конструктора класса.
|
`UserFinderInterface`; класс `UserFinder` реализует этот интерфейс и зависит от объекта `Connection`. Все эти зависимости
|
||||||
При регистрации зависимости через свойство, контейнер внедрения зависимостей позволяет автоматически разрешить эти зависимости и создаёт новый экземпляр `UserLister` простым вызовом `get('userLister')`.
|
были объявлены через тип подсказки параметров конструктора класса. При регистрации зависимости через свойство, контейнер
|
||||||
|
внедрения зависимостей позволяет автоматически разрешить эти зависимости и создаёт новый экземпляр `UserLister` простым
|
||||||
|
вызовом `get('userLister')`.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
namespace app\models;
|
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 создаёт контейнер внедрения зависимостей когда вы подключаете файл `Yii.php` во [входном скрипте](structure-entry-scripts.md)
|
||||||
вашего приложения. Контейнер внедрения зависимостей доступен через [[Yii::$container]]. При вызове [[Yii::createObject()]],
|
вашего приложения. Контейнер внедрения зависимостей доступен через [[Yii::$container]]. При вызове [[Yii::createObject()]],
|
||||||
метод на самом деле вызовет метод контейнера [[yii\di\Container::get()|get()]], чтобы создать новый объект.
|
метод на самом деле вызовет метод контейнера [[yii\di\Container::get()|get()]], чтобы создать новый объект.
|
||||||
Как упомянуто выше, контейнер внедрения зависимостей автоматически разрешит зависимости (если таковые имеются) и внедрит их в только что созданный объект.
|
Как упомянуто выше, контейнер внедрения зависимостей автоматически разрешит зависимости (если таковые имеются) и внедрит их
|
||||||
Поскольку Yii использует [[Yii::createObject()]] в большей части кода своего ядра для создания новых объектов, это означает,
|
получаемый объект. Поскольку Yii использует [[Yii::createObject()]] в большей части кода своего ядра для создания новых
|
||||||
что вы можете настроить глобальные объекты, имея дело с [[Yii::$container]].
|
объектов, это означает, что вы можете настроить глобальные объекты, имея дело с [[Yii::$container]].
|
||||||
|
|
||||||
Например, вы можете настроить по умолчанию глобальное количество кнопок в пейджере [[yii\widgets\LinkPager]]:
|
Например, давайте настроим количество кнопок в пейджере [[yii\widgets\LinkPager]] по умолчанию глобально:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);
|
\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>
|
Итог <span id="summary"></span>
|
||||||
|
|||||||
Reference in New Issue
Block a user