mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-11-04 14:46:19 +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