• Час читання ~4 хв
  • 03.06.2022

Для тих, хто не користувався постачальниками послуг у Laravel, це містичний «термін»: яку «послуги» вони насправді «надають», і як саме все це працює? Я поясню це в цій статті.


Постачальники послуг Laravel за умовчанням

Почнемо з постачальників послуг за замовчуванням, включених до Laravel, усі вони знаходяться в папці app/Providers:

  • AppServiceProvider
  • AuthServiceProvider
  • BroadcastServiceProvider
  • EventServiceProvider
  • RouteServiceProvider

Всі вони є класами PHP, кожен з яких пов’язаний зі своєю темою: загальні "програми", Auth, Broadcasting, Events і Routes. Але всі вони мають одну спільну рису: метод boot().

Усередині цього методу ви можете написати будь-який код, пов’язаний з одним із цих розділів: auth, події, маршрути тощо. Іншими словами, постачальники послуг – це просто класи для реєстрації певної глобальної функціональності.

Вони відокремлені як «постачальники», оскільки вони виконуються дуже на початку життєвого циклу програми, тому тут зручно щось глобальне, перш ніж сценарій виконання надходить до моделей або контролерів.

Найбільше функцій міститься в RouteServiceProvider, давайте подивимося на його код:

class RouteServiceProvider extends ServiceProvider
{
    public const HOME = '/dashboard';
 
    public function boot()
    {
        $this->configureRateLimiting();
 
        $this->routes(function () {
            Route::prefix('api')
                ->middleware('api')
                ->group(base_path('routes/api.php'));
 
            Route::middleware('web')
                ->group(base_path('routes/web.php'));
        });
    }
 
    protected function configureRateLimiting()
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });
    }
}

Це клас, у якому налаштовуються файли маршрутів із routes/web.php і routes/api.php, включеними за замовчуванням.Зверніть увагу, що для API також існують різні конфігурації: префікс кінцевої точки /api і проміжне програмне забезпечення api для всіх маршрутів.

Ви можете редагувати цих постачальників послуг як завгодно, вони не знаходяться в папці /vendor. Типове налаштування цього файлу відбувається, коли у вас є багато маршрутів, і ви хочете розділити їх у своєму файлі.Ви створюєте routes/auth.php і розміщуєте туди маршрути, а потім "включаєте" цей файл у методі boot() RouteServiceProvider, просто додайте третє речення:

`Route::middleware('web') // or maybe you want another middleware?
    ->group(base_path('routes/auth.php'));

Інші постачальники послуг за замовчуванням мають інші функції, ви можете проаналізувати їх самостійно.За винятком AppServiceProvider, він порожній, як заповнювач для додавання будь-якого коду, пов’язаного з деякими глобальними налаштуваннями програми.

Один популярний приклад додавання коду до AppServiceProvider — це вимкнення ліниве завантаження в Eloquent.Для цього вам просто потрібно додати два рядки в метод boot():

// app/Providers/AppServiceProvider.php
use Illuminate\Database\Eloquent\Model;
 
public function boot()
{
    Model::preventLazyLoading(! $this->app->isProduction());
}

Це створить виняток, якщо деяка модель відносин не буде завантажена, що спричинить так звану проблему запиту N+1 з продуктивністю.


Коли виконуються постачальники послуг?

Якщо ви подивитеся на офіційні документи про життєвий цикл запиту, то це те, що виконується на самому початку:

  • public/index.php
  • bootstrap/app.php
  • app/Http/Kernel.php and its Middlewares
  • Service Providers: exactly our topic of this article

Які постачальники завантажені? Він визначається в config/app.

return [
 
	// ... other configuration values
 
    'providers' => [
 
        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
 
        // ... other framework providers from /vendor
        Illuminate\Validation\ValidationServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,
 
        /*
         * PUBLIC Service Providers - the ones we mentioned above
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
 
    ],
 
];

Створіть свого постачальника послуг

На додаток до існуючих файлів за замовчуванням, ви можете легко створити свого постачальника послуг, пов’язаних з деякими іншими темами, ніж стандартні, наприклад auth/event/routes.

Досить типовим прикладом є конфігурація, пов’язана з переглядами Blade.Якщо ви хочете створити свою директиву Blade, ви можете додати цей код до методу boot() будь-якого постачальника послуг, включаючи стандартний AppServiceProvider, але досить часто розробники створюють окремий ViewServiceProvider .

Ви можете створити його за допомогою цієї команди:

Це створить шаблон за замовчуванням:


Ви можете видалити метод register(), а всередині boot() додати код директиви Blade:

Інший приклад ViewServiceProvider стосується View Composers, ось фрагмент з офіційних документів Laravel:

Для виконання цього нового постачальника слід додати до масиву постачальників у config/app.php, як зазначено вище:

Приклади з проектів з відкритим кодом

php artisan make:provider ViewServiceProvider

На завершення я хочу згадати кілька прикладів із вільно доступних проектів Laravel.

namespace App\Providers;
 
use Illuminate\Support\ServiceProvider;
 
class ViewServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
 
    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

Один із найпопулярніших проектів з відкритим кодом Laravel має окремий файл для реєстрації макросів колекції:

use Illuminate\Support\Facades\Blade;
 
public function boot()
{
    Blade::directive('datetime', function ($expression) {
        return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
    });
}

Відома компанія Spatie опублікувала вихідний код для особистого блогу Freek Van der Herten з цим файлом.

use App\View\Composers\ProfileComposer;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
 
class ViewServiceProvider extends ServiceProvider
{
    public function boot()
    {
        // Using class based composers...
        View::composer('profile', ProfileComposer::class);
 
        // Using closure based composers...
        View::composer('dashboard', function ($view) {
            //
        });
    }
}

return [ // ... other configuration values   'providers' => [   App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class,   // Add your provider here App\Providers\ViewServiceProvider::class, ], ];


Переглянути джерело на Github

Переглянути джерело на Github

Один із найпопулярніших проектів з відкритим кодом Laravel має окремий файл для реєстрації макросів колекції:

namespace App\Providers;   use App\Http\Components\AdComponent; use Illuminate\Support\Facades\Blade; use Illuminate\Support\ServiceProvider;   class BladeComponentServiceProvider extends ServiceProvider { public function boot() { Blade::component('ad', AdComponent::class);   Blade::component('front.components.inputField', 'input-field'); Blade::component('front.components.submitButton', 'submit-button'); Blade::component('front.components.textarea', 'textarea'); Blade::component('front.components.textarea', 'textarea'); Blade::component('front.components.shareButton', 'share-button'); Blade::component('front.components.lazy', 'lazy'); Blade::component('front.components.postHeader', 'post-header');   Blade::component('front.layouts.app', 'app-layout'); } }

Переглянути джерело на Github

Ви також можете знайти ще кілька прикладів постачальників послуг на моєму веб-сайті LaravelExamples.com.

namespace App\Providers;
 
use App\Helpers\CollectionHelper;
use Illuminate\Support\Collection;
use Illuminate\Support\ServiceProvider;
 
class MacroServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        if (! Collection::hasMacro('sortByCollator')) {
            Collection::macro('sortByCollator', function ($callback, $options = \Collator::SORT_STRING, $descending = false) {
                /** @var Collection */
                $collect = $this;
 
                return CollectionHelper::sortByCollator($collect, $callback, $options, $descending);
            });
        }
 
        if (! Collection::hasMacro('groupByItemsProperty')) {
            Collection::macro('groupByItemsProperty', function ($property) {
                /** @var Collection */
                $collect = $this;
 
                return CollectionHelper::groupByItemsProperty($collect, $property);
            });
        }
 
        if (! Collection::hasMacro('mapUuid')) {
            Collection::macro('mapUuid', function () {
                /** @var Collection */
                $collect = $this;
 
                return $collect->map(function ($item) {
                    return $item->uuid;
                })->toArray();
            });
        }
    }
}
 
namespace App\Providers;
 
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Blade;
use App\Helpers\FileUpload\UploadComponents;
 
class DashboardComponentsServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
 
    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('uploadForm', function () {
            $component = UploadComponents::getUploadForm();
            $html = '<?php echo \'' . $component . '\'; ?>';
 
            return ('<?php echo "' . $component . '"; ?>');
        });
    }
}

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297