Skip to content

Latest commit

 

History

History
163 lines (115 loc) · 8.56 KB

providers.md

File metadata and controls

163 lines (115 loc) · 8.56 KB

git 41fca1588af2175b2fe340a3c332322db7646963


Service Providers

Введение

Service providers (сервис-провайдеры, дословно - "поставщики услуг") занимают центральное место в архитектуре Laravel. Они предназначены для первоначальной загрузки (bootstraping) приложения. Ваше приложение, а также сервисы самого фреймворка загружаются через сервис-провайдеры.

Что конкретно означает термин "первоначальная загрузка" или "bootsraping"? Главным образом это регистрация некоторых вещей - таких как биндинги в IoC-контейнер (фасадов и т.д.), слушателей событий (event listeners), фильтров роутов (route filters) и самих роутов (routes). Сервис-провайдеры - центральное место для конфигурирования вашего приложения.

Если вы откроете файл config/app.php, вы увидите массив providers. В нем перечислены все классы сервис-провайдеров, которые загружаются при старте вашего приложения (конечно, кроме тех, которые являются "отложенными" (deferred), т.е. загружаются по требованию другого сервис-провайдера).

Можно и нужно создавать свои собственные сервис-провайдеры для загрузки и настройки различных частей своего приложения.

Использование провайдеров

Сервис-провайдеры должны расширять (extends) класс Illuminate\Support\ServiceProvider. Это абстрактный класс, который требует, чтобы в наследуемом классе был метод register(). В методе register() вы можете только регистрировать свои классы (bindings) в сервис-контейнере. Слушателей событий (event listeners), роуты и фильтры роутов там регистрировать нельзя.

С помощью Artisan можно легко создать нового провайдера, используя команду make:provider:

php artisan make:provider RiakServiceProvider

Метод register()

Вот так может выглядеть простейший сервис-провайдер:

<?php namespace App\Providers;

use Riak\Connection;
use Illuminate\Support\ServiceProvider;

class RiakServiceProvider extends ServiceProvider {

	/**
	 * Register bindings in the container.
	 *
	 * @return void
	 */
	public function register()
	{
		$this->app->singleton('Riak\Contracts\Connection', function($app)
		{
			return new Connection($app['config']['riak']);
		});
	}

}

В register() мы регистрируем (bind) как singleton (т.е. класс не будет переинициализироваться после вызова из контейнера) в сервис-контейнере класс работы с базой данных Riak. Если для вас этот код выглядит абракадаброй, не беспокойтесь, работу сервис-контейнера мы рассмотрим позже.

Неймспейс App\Providers, в котором находится этот класс сервис-провайдера - дефолтное место для хранения сервис-провайдеров вашего Laravel-приложения, но вы можете располагать свои сервис-провайдеры где угодно внутри вашей PSR-4 папки (если вы не меняли composer.json, то это папка app).

Метод boot()

Когда вызвались методы register() всех сервис-провайдеров приложения, вызывается метод boot() сервис-провайдеров. Там уже можно использовать весь существующий функционал классов фреймворка и вашего приложения - регистрировать слушателей событий, подключать роуты и т.п.

<?php namespace App\Providers;

use Event;
use Illuminate\Support\ServiceProvider;

class EventServiceProvider extends ServiceProvider {

	/**
	 * Perform post-registration booting of services.
	 *
	 * @return void
	 */
	public function boot(Dispatcher $events)
	{
		Event::listen('SomeEvent', 'SomeEventHandler');
	}

	/**
	 * Register bindings in the container.
	 *
	 * @return void
	 */
	public function register()
	{
		//
	}

}

Обратите внимание, что сервис-контейнер, вызывая метод boot(), сам инъектирует те зависимости, которые вы зададите, в частности, Dispatcher.

use Illuminate\Contracts\Events\Dispatcher;

public function boot(Dispatcher $events)
{
	$events->listen('SomeEvent', 'SomeEventHandler');
}

Регистрация провайдеров

Все сервис-провайдеры регистрируются в файле config/app.php путем добавления в массив providers. Все сервис-провайдеры фреймворка находятся там.

Чтобы зарегистрировать свой сервис-провайдер, добавьте название класса в этот массив:

'providers' => [
	// другие сервис-провайдеры

	'App\Providers\AppServiceProvider',
],

Отложенные провайдеры

Если ваш провайдер только регистрирует (bind) классы в сервис-контейнере, то вы можете отложить вызов его метода register() до момента, когда эти классы будут затребованы из сервис-контейнера. Это позволит не дергать файловую систему каждый запрос в попытках загрузить файл с нужным классом с диска.

Для того, чтобы сделать сервис-провайдер отложенным, установите свойство defer в true и определить метод provides(), чтобы фреймворк знал, какие классы биндятся (регистрируются в сервис-контейнере, "связываются") в вашем провайдере.

<?php namespace App\Providers;

use Riak\Connection;
use Illuminate\Support\ServiceProvider;

class RiakServiceProvider extends ServiceProvider {

	/**
	 * Indicates if loading of the provider is deferred.
	 *
	 * @var bool
	 */
	protected $defer = true;

	/**
	 * Register the service provider.
	 *
	 * @return void
	 */
	public function register()
	{
		$this->app->singleton('Riak\Contracts\Connection', function($app)
		{
			return new Connection($app['config']['riak']);
		});
	}

	/**
	 * Get the services provided by the provider.
	 *
	 * @return array
	 */
	public function provides()
	{
		return ['Riak\Contracts\Connection'];
	}

}

Laravel в процессе запуска собирает данные об отложенных сервис-провайдерах и классах, которые ими биндятся, и когда в процессе работы приложению понадобится класс Riak\Contracts\Connection, он вызовет метод register() сервис провайдера RiakServiceProvider.