Service Providers in Laravel: What They Are and How to Use Them

Published on by

Service Providers in Laravel: What They Are and How to Use Them image

For those who haven't actively used Service Providers in Laravel, it's a mystical "term": what "service" do they actually "provide", and how exactly does it all work? I will explain it in this article.


Default Laravel Service Providers

Let's start with the default service providers included in Laravel, they are all in the app/Providers folder:

  • AppServiceProvider
  • AuthServiceProvider
  • BroadcastServiceProvider
  • EventServiceProvider
  • RouteServiceProvider

They are all PHP classes, each related to its topic: general "app", Auth, Broadcasting, Events, and Routes. But they all have one thing in common: the boot() method.

Inside of that method, you can write any code related to one of those sections: auth, events, routes, etc. In other words, Service Providers are just classes to register some global functionality.

They are separated as "providers" because they are executed really early in the Application Lifecycle, so it is convenient something global here before the execution script comes to Models or Controllers.

The most amount of functionality is in the RouteServiceProvider, let's take a look at its code:

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

This is the class where route files are configured, with routes/web.php and routes/api.php included by default. Notice that for the API there are also different configurations: endpoint prefix /api and middleware api for all the routes.

You can edit those Service Providers however you want, they are not in the /vendor folder. Typical customization of this file happens when you have a lot of routes and you want to separate them in your custom file. You create routes/auth.php and put the routes there, and then you "enable" that file in the boot() method of the RouteServiceProvider, just add the third sentence:

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

Other default service providers have other functionality, you can analyze them by yourself. Except for AppServiceProvider, it is empty, like a placeholder for us to add any code related to some global application settings.

One popular example of adding code to the AppServiceProvider is about disabling the lazy loading in Eloquent. To do that, you just need to add two lines into the boot() method:

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

This will throw an exception if some relationship model isn't eager loaded, which causes a so-called N+1 query problem with performance.


When Service Providers Are Executed?

If you look at the official docs about request lifecycle, these are the things executed in the very beginning:

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

Which providers are loaded? It's defined in the config/app.php array:

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

As you can see, there's a list of non-public service providers from the /vendor folder, you shouldn't touch/edit them. The ones we're interested in are at the bottom, with BroadcastServicerProvider disabled by default, probably because it's rarely used.

All of those service providers are executed from top to bottom, iterating that list twice.

The first iteration is looking for an optional method register() which may be used to initiate something before the boot() method. I've never used it in my experience.

Then, the second iteration executes the boot() method of all providers. Again, one by one, from top to bottom of the 'providers' array.

And then, after all the service providers have been processed, Laravel goes to parsing the route, executing the Controller, using Models, etc.


Create Your Custom Service Provider

In addition to the existing default files, you can easily create your service provider, related to some other topics than the default ones like auth/event/routes.

Quite a typical example is configuration related to Blade views. If you want to create your Blade directive, you can add that code into any service provider's boot() method, including the default AppServiceProvider, but quite often developers create a separate ViewServiceProvider.

You can generate it with this command:

php artisan make:provider ViewServiceProvider

It will generate the default template:

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

You may remove the register() method, and inside of boot() add Blade directive code:

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

Another example of a ViewServiceProvider is about View Composers, here's the snippet from the official Laravel docs:

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

To be executed, this new provider should be added to the array of providers in config/app.php, as mentioned above:

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

Examples from Open-Source Projects

Finally, I want to mention a few examples from freely available Laravel projects.

1. spatie/freek.dev: BladeComponentServiceProvider

A well-known company Spatie has published the source code for the personal blog of Freek Van der Herten, with this file.

app/Providers/BladeComponentServiceProvider.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');
}
}

View source on Github

2. monicahq/monica: MacroServiceProvider

One of the most-starred Laravel open-source projects has a separate file to register Collection macros:

app/Providers/MacroServiceProvider.php:

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

View source on Github

3. phpreel/phpreelcms: DashboardComponentsServiceProvider

Laravel CMS called phpReel also has a service provider for Blade components, named even longer.

app/Providers/DashboardComponentsServiceProvider.php:

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

View source on Github

You can also find a few more examples of Service Providers at my LaravelExamples.com website.

PovilasKorop photo

Creator of Courses and Tutorials at Laravel Daily

Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

Laravel Forge logo

Laravel Forge

Easily create and manage your servers and deploy your Laravel applications in seconds.

Laravel Forge
Tinkerwell logo

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
No Compromises logo

No Compromises

Joel and Aaron, the two seasoned devs from the No Compromises podcast, are now available to hire for your Laravel project. ⬧ Flat rate of $7500/mo. ⬧ No lengthy sales process. ⬧ No contracts. ⬧ 100% money back guarantee.

No Compromises
Kirschbaum logo

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift
Bacancy logo

Bacancy

Supercharge your project with a seasoned Laravel developer with 4-6 years of experience for just $2500/month. Get 160 hours of dedicated expertise & a risk-free 15-day trial. Schedule a call now!

Bacancy
Lucky Media logo

Lucky Media

Get Lucky Now - the ideal choice for Laravel Development, with over a decade of experience!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel E-Commerce

E-Commerce for Laravel. An open-source package that brings the power of modern headless e-commerce functionality to Laravel.

Lunar: Laravel E-Commerce
LaraJobs logo

LaraJobs

The official Laravel job board

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Multi-tenant Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit
Supercharge Your SaaS Development with FilamentFlow: The Ultimate Laravel Filament Boilerplate logo

Supercharge Your SaaS Development with FilamentFlow: The Ultimate Laravel Filament Boilerplate

Build your SaaS application in hours. Out-of-the-box multi-tenancy and seamless Stripe integration. Supports subscriptions and one-time purchases, allowing you to focus on building and creating without repetitive setup tasks.

Supercharge Your SaaS Development with FilamentFlow: The Ultimate Laravel Filament Boilerplate
Rector logo

Rector

Your partner for seamless Laravel upgrades, cutting costs, and accelerating innovation for successful companies

Rector
MongoDB logo

MongoDB

Enhance your PHP applications with the powerful integration of MongoDB and Laravel, empowering developers to build applications with ease and efficiency. Support transactional, search, analytics and mobile use cases while using the familiar Eloquent APIs. Discover how MongoDB's flexible, modern database can transform your Laravel applications.

MongoDB

The latest

View all →
Asymmetric Property Visibility in PHP 8.4 image

Asymmetric Property Visibility in PHP 8.4

Read article
Access Laravel Pulse Data as a JSON API image

Access Laravel Pulse Data as a JSON API

Read article
Laravel Forge adds Statamic Integration image

Laravel Forge adds Statamic Integration

Read article
Transform Data into Type-safe DTOs with this PHP Package image

Transform Data into Type-safe DTOs with this PHP Package

Read article
PHPxWorld - The resurgence of PHP meet-ups with Chris Morrell image

PHPxWorld - The resurgence of PHP meet-ups with Chris Morrell

Read article
Herd Executable Support and Pest 3 Mutation Testing in PhpStorm 2024.3 image

Herd Executable Support and Pest 3 Mutation Testing in PhpStorm 2024.3

Read article