Прежде чем перейти к обсуждению провайдера, или поставщика услуг (ServiceProvider), рассмотрим контейнер сервисов (ServiceContainer), который используется провайдером.
Контейнер
Когда вам нужно встроить какой-либо класс, вы можете указать его в своем конструкторе или методе, и он будет автоматически встраиваться из контейнера служб. Это избавляет вас от ручной компоновки компонентов и, таким образом, позволяет избежать жесткой связи в вашем коде.
Рассмотрим пример.
Class SomeClass { public function __construct(FooBar $foo) { // use $foo object } }
SomeClass
нуждается в экземпляре FooBar
для создания экземпляра.Laravel находит соостветствующий контейнер и внедряет зависимость, т.е. объект $foo класса FooBar.
В файле config/app.php
имеется массив, в котором перечислены все сервис провайдеры, которые будут загружены во время начальной загрузки приложения Laravel.
'providers' => [ /* * Laravel Framework Service Providers... */ Illuminate\Auth\AuthServiceProvider::class, Illuminate\Broadcasting\BroadcastServiceProvider::class, Illuminate\Bus\BusServiceProvider::class, Illuminate\Cache\CacheServiceProvider::class, Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, Illuminate\Cookie\CookieServiceProvider::class, Illuminate\Database\DatabaseServiceProvider::class, Illuminate\Encryption\EncryptionServiceProvider::class, Illuminate\Filesystem\FilesystemServiceProvider::class, Illuminate\Foundation\Providers\FoundationServiceProvider::class, Illuminate\Hashing\HashServiceProvider::class, Illuminate\Mail\MailServiceProvider::class, Illuminate\Notifications\NotificationServiceProvider::class, Illuminate\Pagination\PaginationServiceProvider::class, Illuminate\Pipeline\PipelineServiceProvider::class, Illuminate\Queue\QueueServiceProvider::class, Illuminate\Redis\RedisServiceProvider::class, Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, Illuminate\Session\SessionServiceProvider::class, Illuminate\Translation\TranslationServiceProvider::class, Illuminate\Validation\ValidationServiceProvider::class, Illuminate\View\ViewServiceProvider::class, /* * Package Service Providers... */ /* * Application Service Providers... */ App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, ],
Обратите внимание, что первыми должны внедряться провайдеры ядра, потом внешних приложений, и только потом провайдеры приложения.
Провайдер
Если контейнер - это то, что позволяет вам определять привязки и устанавливать зависимости, сервис провайдер - это место, где все это происходит.
Давайте быстро взглянем на одного из основных сервис провайдеров, чтобы понять, что он делает. Откройте файл vender/laravel/framework/src/Illuminate/Cache/CacheServiceProvider.php.
Провайдер регистрирует все привязки контейнера, и это делается с помощью метода register реализации сервис провайдера.
Основная задача поставщика услуг, или ServiceProviders – это загрузка вспомогательных, в том числе, и собственных классов.
Если открыть конфигурационный файлa app.php, то мы увидим там множество провайдеров, определенных в массиве providers. Это все классы, которые будут загружены для приложения. Многие из них являются отложенными, что означает, что они не будут загружаться при каждом запросе, а только тогда, когда они действительно необходимы, т.е. когда они будут вызываться.
Регистрация ServiceProviders осуществляется в файле config/app.php
'providers' => [ // другие сервис-провайдеры 'App\Providers\AppServiceProvider', ],
Все провайдеры должны наследоваться от класса Illuminate\Support\ServiceProvider. Данный абстрактный класс требует, чтобы был определен хотя бы один метод класса-провайдера: register. В этом методе регистрируется вспомогательный класс.
Сам провайдер можно создать с помощью artisan:
php artisan make:provider ProductServiceProvider
В папке providers/ появился файл ProductServiceProvider.
Класс ProductServiceProvider содержит методы boot() и register(). register() предназначен для регистрации вспомогательных классов, boot() - для всего остального.
Передача переменных в базовый шаблон
Одним из самых частых применений метода boot() является передача переменных в шаблоны. Объявить переменные для любого шаблона или группы шаблонов. Рассмотрим, как это сделать.
1. Создадим провайдер VarsServiceProvider:
php artisan make:provider VarsServiceProvider
2. Исходный код файла VarsServiceProvider:
namespace App\Providers; use Illuminate\Support\ServiceProvider; use View; class VarsServiceProvider extends ServiceProvider { public function boot(){ View::composer('layouts.base', 'App\Providers\ViewComposers\BaseComposer'); } public function register(){ // } }
3. В дирректории App\Providers cоздадим папку ViewComposers
4. В папке ViewComposers создадим файл BaseComposer. Исходный код файла BaseComposer.php:
namespace App\Providers\ViewComposers; use Illuminate\Contracts\View\View; use App\Category; class BaseComposer{ public function compose(View $view){ $categories = Category::all(); $view->with('categories', $categories); } }
5. Если всё сделали правильно, в шаблоне base.blade.php будет доступна переменная (массив объектов) $categories.
@foreach($categories as $one) {{$cat->name}} @endforeach