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 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 Możesz go wygenerować za pomocą tego polecenia: Wygeneruje domyślny szablon: Możesz usunąć metodę 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 Na koniec chciałbym wspomnieć o kilku przykładach z swobodnie dostępnych projektów Laravel. Znana firma Spatie opublikowała kod źródłowy osobistego bloga Freeka Van der Hertena za pomocą tego pliku. p>
aplikacja/Providers/BladeComponentServiceProvider.php: Jeden z najpopularniejszych projektów open-source Laravel ma osobny plik do rejestrowania makr kolekcji: aplikacja/Providers/MacroServiceProvider.php: aplikacja/Dostawcy/DashboardComponentsServiceProvider.php: Możesz również znaleźć kilka innych przykładów Usługodawców na mojej stronie LaravelExamples.com.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
boot()
dowolnego dostawcy usług, w tym domyślnej AppServiceProvider
, ale dość często programiści tworzą osobny ViewServiceProvider .
register()
, a wewnątrz boot()
dodać kod dyrektywy Blade:config/app.php
, jak wspomniano powyżej:Przykłady z projektów Open Source
php artisan make:provider ViewServiceProvider
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'); ?>";
});
}
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,
],
];
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');
}
}
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 . '"; ?>');
});
}
}