• Czas czytania ~4 min
  • 03.06.2022

Dla tych, którzy nie korzystali aktywnie z dostawców usług w Laravel, jest to mistyczne „termin”: jaką „usługę” faktycznie „zapewniają” i jak dokładnie to wszystko działa? Wyjaśnię to w tym artykule.


Domyślni dostawcy usług Laravel

Zacznijmy od domyślnych dostawców usług zawartych w Laravel, wszyscy znajdują się w folderze app/Providers:

  • AppServiceProvider
  • AuthServiceProvider
  • BroadcastServiceProvider
  • EventServiceProvider
  • RouteServiceProvider

Wszystkie są klasami PHP, z których każda jest związana z jej tematem: ogólna "aplikacja", Auth, Broadcasting, Events i Routes. Ale wszystkie mają jedną wspólną cechę: metodę boot().

Wewnątrz tej metody możesz napisać dowolny kod związany z jedną z tych sekcji: auth, zdarzenia, trasy itp. Innymi słowy, dostawcy usług to tylko klasy rejestrujące jakąś globalną funkcjonalność.

Są one oddzielone jako „dostawcy”, ponieważ są wykonywane na bardzo wczesnym etapie cyklu życia aplikacji, więc wygodniej jest zastosować tutaj coś globalnego, zanim skrypt wykonawczy dotrze do modeli lub kontrolerów.

Najwięcej funkcji znajduje się w RouteServiceProvider, spójrzmy na jego kod:

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());
        });
    }
}

Jest to klasa, w której konfigurowane są pliki tras, z domyślnie dołączonymi routes/web.php i routes/api.php.Zauważ, że dla API istnieją również różne konfiguracje: prefiks punktu końcowego /api i oprogramowanie pośrednie api dla wszystkich tras.

Możesz edytować tych dostawców usług w dowolny sposób, nie ma ich w folderze /vendor. Typowe dostosowywanie tego pliku ma miejsce, gdy masz wiele tras i chcesz je rozdzielić w swoim niestandardowym pliku.Tworzysz routes/auth.php i umieszczasz tam trasy, a następnie "włączasz" ten plik w metodzie boot() RouteServiceProvider, po prostu dodaj trzecie zdanie:

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

Inni domyślni dostawcy usług mają inne funkcje, które możesz samodzielnie przeanalizować.Z wyjątkiem AppServiceProvider, jest on pusty, jak symbol zastępczy dla nas, aby dodać dowolny kod związany z niektórymi globalnymi ustawieniami aplikacji.

Jednym z popularnych przykładów dodawania kodu do AppServiceProvider jest wyłączenie leniwe ładowanie w Eloquent.Aby to zrobić, wystarczy dodać dwie linie do metoda boot():

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

Spowoduje to zgłoszenie wyjątku, jeśli jakiś model relacji nie zostanie szybko załadowany, co powoduje tak zwany problem z zapytaniem N+1 z wydajnością.


Kiedy świadczeni są dostawcy usług?

Jeśli spojrzysz na oficjalne dokumenty dotyczące cyklu życia żądania, oto rzeczy wykonane na samym początku:

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

Którzy dostawcy są załadowani? Jest zdefiniowany w 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,
 
    ],
 
];

Utwórz własnego dostawcę usług niestandardowych

Oprócz istniejących plików domyślnych, możesz łatwo utworzyć dostawcę usług związanych z niektórymi innymi tematami niż domyślne, takie jak auth/event/routes.

Całkiem typowym przykładem jest konfiguracja związana z widokami Blade.Jeśli chcesz utworzyć dyrektywę Blade, możesz dodać ten kod do metody boot() dowolnego dostawcy usług, w tym domyślnej AppServiceProvider, ale dość często programiści tworzą osobny ViewServiceProvider .

Możesz go wygenerować za pomocą tego polecenia:

Wygeneruje domyślny szablon:


Możesz usunąć metodę register(), a wewnątrz boot() dodać kod dyrektywy Blade:

Kolejny przykład ViewServiceProvider dotyczy kompozytorów widoków, oto fragment z oficjalnych dokumentów Laravela:

Aby wykonać, ten nowy dostawca powinien zostać dodany do tablicy dostawców w config/app.php, jak wspomniano powyżej:

Przykłady z projektów Open Source

php artisan make:provider ViewServiceProvider

Na koniec chciałbym wspomnieć o kilku przykładach z swobodnie dostępnych projektów 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()
    {
        //
    }
}

1. spatie/freek.deweloper: BladeComponentServiceProvider

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

Znana firma Spatie opublikowała kod źródłowy osobistego bloga Freeka Van der Hertena za pomocą tego pliku.

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) {
            //
        });
    }
}

aplikacja/Providers/BladeComponentServiceProvider.php:

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,
    ],
];

Wyświetl źródło na Github

Wyświetl źródło na Github

Jeden z najpopularniejszych projektów open-source Laravel ma osobny plik do rejestrowania makr kolekcji:

aplikacja/Providers/MacroServiceProvider.php:

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'); } }

aplikacja/Dostawcy/DashboardComponentsServiceProvider.php:

Wyświetl źródło na Github

Możesz również znaleźć kilka innych przykładów Usługodawców na mojej stronie 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

O

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...

O autorze CrazyBoy49z
WORK EXPERIENCE
Kontakt
Ukraine, Lutsk
+380979856297