Какова концепция сервисного контейнера в Laravel?
Я начинаю изучать Laravel, но я не понимаю концепцию сервисного контейнера.
Как это работает и что нужно знать разработчикам, чтобы полностью использовать эту концепцию в Laravel?
2 answers
Контейнер службы в Laravel - это контейнер для внедрения зависимостей и реестр для приложения
Преимущества использования контейнера службы по сравнению с созданием объектов вручную заключаются в следующем:
Способность управлять зависимостями классов при создании объектов
Вы определяете, как объект должен быть создан в одной точке приложения (привязка), и каждый раз, когда вам нужно создать новый экземпляр, вы просто задаете его службе контейнер, и он создаст его для вас вместе с необходимыми зависимостями
Например, вместо создания объектов вручную с помощью ключевого слова new
:
//every time we need YourClass we should pass the dependency manually
$instance = new YourClass($dependency);
Вы можете зарегистрировать привязку к контейнеру службы:
//add a binding for the class YourClass
App::bind( YourClass::class, function()
{
//do some preliminary work: create the needed dependencies
$dependency = new DepClass( config('some.value') );
//create and return the object with his dependencies
return new YourClass( $dependency );
});
И создайте экземпляр через контейнер службы с помощью:
//no need to create the YourClass dependencies, the SC will do that for us!
$instance = App::make( YourClass::class );
Привязка интерфейсов к конкретным классам
С автоматической инъекцией зависимостей Laravel, когда требуется интерфейс в какой-то части приложение (т. Е. в конструкторе контроллера), конкретный класс создается автоматически контейнером службы. Изменение конкретного класса в привязке приведет к изменению конкретных объектов, созданных во всех ваших приложениях:
//everityme a UserRepositoryInterface is requested, create an EloquentUserRepository
App::bind( UserRepositoryInterface::class, EloquentUserRepository::class );
//from now on, create a TestUserRepository
App::bind( UserRepositoryInterface::class, TestUserRepository::class );
Использование контейнера службы в качестве реестра
Вы можете создавать и хранить уникальные экземпляры объектов в контейнере и возвращать их позже: используя метод App::instance
для создания привязки и, таким образом, используя контейнер в качестве Реестр.
// Create an instance.
$kevin = new User('Kevin');
// Bind it to the service container.
App::instance('the-user', $kevin);
// ...somewhere and/or in another class...
// Get back the instance
$kevin = App::make('the-user');
В качестве заключительного замечания, по сути, Сервисный контейнер - это объект Application
: он расширяет класс Container
, получая все функциональные возможности контейнера
Контейнер Laravel создает экземпляр для полного приложения из служб (класс)
Нам не нужно создавать instance
для нашего приложения, например
$myclass = new MyClass();
$mymethod = $myclass->myMethod();
Приложение::привязка
Во-первых, мы рассмотрим статический метод класса App
. bind
просто связывает ваш класс instance
(объект) с приложением, не более того.
App::bind('myapp', function(){
return new MyClass();
});
Теперь мы можем использовать этот объект для нашего приложения, используя make
статический метод класса App
.
$myclass = App::make(MyClass::class);
$mymethod = $myclass->myMethod();
Приложение::синглтон
В приведенном выше примере, когда мы собираемся вызвать метод make
, то он генерирует каждый раз новый instance
класса, поэтому у Laravel есть красивое решение для Singleton
Мы можем привязать object
к нашему приложению методом singleton
.
App::singleton(MyClass::class, function(){
return new MyClass();
});
Мы можем быть решены методом make
. Теперь мы всегда получали один и тот же экземпляр от этого метода.
$myclass = App::make(MyClass::class);
$mymethod = $myclass->myMethod();
Приложение::экземпляр
Мы можем привязать экземпляр к контейнеру, и мы всегда будем возвращать одно и то же экземпляр, использующий метод instance
.
$myclass = new MyClass();
App::instance(MyClass::class, $myclass);
Мы можем быть решены с помощью
$myclass = App::make(MyClass::class);
Мы можем связать интерфейс с помощью
App::instance(MyClassInterface::class, new MyClass);
Обязательная реализация
Да, у нас есть вопрос, как мы можем реализовать привязку в нашем приложении? Мы можем реализовать привязку в нашем AppServiceProvider
app/Providers/AppServiceProvider.php
namespace App\Providers;
use App\SocialProvider;
use App\TwitterSocialProvider;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->bind(
MyClassInterface::class,
MyClass::class
);
}
}
Вывод: Контейнер службы помогает создавать объекты класса или службы.