Может войдёшь?
Черновики Написать статью Профиль

Обратное управление (IoC)

перевод документация 4.x

  1. 1. Введение
  2. 2. Основы использования
  3. 3. Где регистрировать привязки
  4. 4. Автоматическое определение
  5. 5. Практическое использование
  6. 6. Поставщики услуг
  7. 7. События контейнера
Этот перевод актуален для англоязычной документации на (ветка 4.1) и (ветка 4.0). Опечатка? Выдели и нажми Ctrl+Enter.

Введение

Класс-контейнер обратного управления IoC Laravel — мощное средство для управления зависимостями классов. Внедрение зависимостей — это способ исключения вшитых (hardcoded) взаимосвязей классов. Вместо этого зависимости определяются во время выполнения, что даёт бо́льшую гибкость благодаря тому, что они могут быть легко изменены.

Понимание IoC-контейнера Laravel необходимо для построения больших и мощных приложений, так же как и для внесения изменений в код ядра самого фреймворка.

Основы использования

Помещение типа в контейнер

Есть два способа, которыми IoC-контейнер разрешает зависимости: через функцию-замыкание и через автоматическое определение. Для начала мы исследуем замыкания. Первым делом некий «тип» должен быть помещён в контейнер:

PHP
App::bind('foo', function ($app) {
  return new 
FooBar;
});

Извлечение типа из контейнера

PHP
$value App::make('foo');

При вызове метода PHPApp::make() вызывается соответствующее замыкание и возвращается результат её вызова.

Помещение «разделяемого» типа в контейнер

Иногда вам может понадобиться поместить в контейнер тип, который должен быть извлечён (создан) только один раз, и чтобы все последующие вызовы возвращали бы тот же объект:

PHP
App::singleton('foo', function () {
  return new 
FooBar;
});

Singleton — шаблон проектирования Одиночкаприм. пер.

Помещение готового экземпляра в контейнер

Вы также можете поместить уже созданный экземпляр объекта в контейнер, используя метод PHPinstance():

PHP
$foo = new Foo;

App::instance('foo'$foo);

Где регистрировать привязки

IoC-привязки, как и обработчики событий или фильтры маршрутов, обычно входят в понятие «код автозагрузки». Другими словами они подготавливают ваше приложение к непосредственной обработке запросов, и, как правило, они должны быть выполнены перед вызовом маршрута или контроллера. Как и для большинства другого кода автозагрузки, IoC-привязки всегда можно зарегистрировать в «стартовых» файлах. Кроме того, вы можете создать файл app/ioc.php (имя файла не имеет значения) и затребовать этот файл из «стартового» файла.

Если в вашем приложении очень большое количество IoC-привязок, или вы просто хотите организовать ваши IoC-привязки в отдельных файлах по категориям, вы можете зарегистрировать привязки в поставщике услуг.

Автоматическое определение

Автоопределение класса

Контейнер IoC достаточно мощен, чтобы во многих случаях определять классы автоматически, без дополнительной настройки. Например:

PHP
class FooBar {

  public function 
__construct(Baz $baz)
  {
    
$this->baz $baz;
  }

}

$fooBar App::make('FooBar');

Обратите внимание, что даже без явного помещения класса PHPFooBar в контейнер он всё равно был определён и зависимость PHPBaz была автоматически внедрена в него.

Если тип не был найден в контейнере, IoC будет использовать возможности рефлексии PHP для изучения класса и чтения подсказок типов (type hints) в его конструкторе. С помощью этой информации контейнер сам создаёт экземпляр класса.

Связывание интерфейса и реализации

Однако в некоторых случаях класс может принимать экземпляр интерфейса, а не сам объект. В этом случае нужно использовать метод PHPApp::bind() для извещения контейнера о том, какая именно зависимость должна быть внедрена:

PHP
App::bind('UserRepositoryInterface''DbUserRepository');

Теперь посмотрим на следующий контроллер:

PHP
class UserController extends BaseController {

  public function 
__construct(UserRepositoryInterface $users)
  {
    
$this->users $users;
  }

}

Благодаря тому, что мы связали PHPUserRepositoryInterface с «настоящим» классом, PHPDbUserRepository, он будет автоматически встроен в контроллер при его создании.

Практическое использование

Laravel предоставляет несколько возможностей для использования контейнера IoC для повышения гибкости и стабильности вашего приложения. Основной пример — зависимости при использовании контроллеров. Все контроллеры извлекаются из IoC, что позволяет вам использовать зависимости на основе подсказок типов в их конструкторах — ведь они будут определены автоматически.

Подсказки типов для указания зависимостей контроллера

PHP
class OrderController extends BaseController {

  
// OrderRepository - подсказка типа - имя класса передаваемого аргумента-объекта.
  
public function __construct(OrderRepository $orders)
  {
      
$this->orders $orders;
  }

  public function 
getIndex()
  {
      
$all $this->orders->all();

      return 
View::make('orders'compact('all'));
  }

}

В этом примере класс PHPOrderRepository автоматически встроится в контроллер. Это значит, что при использовании юнит-тестов класс-заглушка для PHPOrderRepository может быть добавлен в контейнер, таким образом легко имитируя взаимодействие с БД.

Другие примеры использования IoC

Фильтры, составители и классы-обработчики могут также извлекаться из IoC. При регистрации этих объектов просто передайте имя класса, который должен быть использован:

PHP
Route::filter('foo''FooFilter');

View::composer('foo''FooComposer');

Event::listen('foo''FooHandler')

Поставщики услуг

Поставщики услуг (service providers) — отличный способ группировки схожих регистраций в IoC в одном месте. Их можно рассматривать как начальный запуск компонентов вашего приложения. Внутри поставщика услуг вы можете зарегистрировать драйвер авторизации, классы-хранилища вашего приложения или даже собственную команду Artisan.

На самом деле большая часть компонентов Laravel включает поставщиков услуг. Все зарегистрированные поставщики в вашем приложении указаны в массиве providers файла настроек app/config/app.php.

Создание поставщика услуг

Для создания нового поставщика просто наследуйте класс PHPIlluminate\Support\ServiceProvider и определите метод PHPregister():

PHP
use Illuminate\Support\ServiceProvider;

class 
FooServiceProvider extends ServiceProvider {

  public function 
register()
  {
    
$this->app->bind('foo', function () {
      return new 
Foo;
    });
  }

}

Заметьте, что внутри метода PHPregister() IoC-контейнер приложения доступен в свойстве PHP$this->app. Как только вы создали поставщика и готовы зарегистрировать его в своём приложении просто добавьте его в массив providers файла настроек app.php.

Регистрация поставщика услуг во время выполнения

Кроме этого, вы можете зарегистрировать его «на лету», используя метод PHPApp::register():

PHP
App::register('FooServiceProvider');

События контейнера

Регистрация обработчика события

Контейнер IoC возбуждает событие каждый раз при извлечении объекта. Вы можете отслеживать его с помощью метода PHPresolvingAny():

PHP
App::resolvingAny(function ($object)
{
  
//
});

App::resolving('foo', function($foo)
{
  
//
});

Созданный объект будет передан в функцию обратного вызова.

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.