Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

sinalco's avatar

Registering service providers

Hi everyone,

I am developing a platform that contains multiple service providers (in the same way as the Laravel framework itself).

I know I can add all these additional service providers in the app.php config file, however I wonder if there isn't a simpler way, by adding only one service provider, which will then register other "internal" providers.

It's technically possible to do this in a service provider…:

public function register()
{
    $this->app->register('Another\Service\Provider');
    // ...
}

… but I'm not sure this is the good way to do this, especially with deferred services.

Any suggestion?

0 likes
11 replies
toniperic's avatar

You can take a look at Illuminate\Auth\AuthServiceProvider as an example of this.

sinalco's avatar

@toniperic Maybe I don't understand what you mean, but Illuminate\Auth\AuthServiceProvider is listed in the providers in app.php, as well as every provider provided by Laravel, and it doesn't register any other provider.

What I want, if possible, would be to add only one provider in this file (for example Acme\AcmeServiceProvider), which will then automatically register Acme\FeatureAServiceProvider, Acme\FeatureBServiceProvider, …

toniperic's avatar

Exactly.

This is the register() method of Illuminate\Auth\AuthServiceProvider

public function register()
{
    $this->registerAuthenticator();
    $this->registerUserResolver();
    $this->registerRequestRebindHandler();
}

What stops you to have the following in your Acme\AcmeServiceProvider

public function register()
{
    $this->registerA();
    $this->registerB();
}
usman's avatar

@toniperic AuthServiceProvider doesn't register other service providers. The register* methods inside the AuthServiceProvider are only binding the dependencies/services related to Authentication Service Layer.

@nmarfurt I would suggest you to use a separate service provider for each service that you are binding with the Service Container and a service provider may contain methods for binding the service dependencies. The AuthServiceProvider is a perfect example of this.

That is what the principle of single responsibility is.

Usman.

PS: For application services you can always utilize the default AppServiceProvider .

bestmomo's avatar

@nmarfurt you'll gain nothing with a custom big service that call all your providers because it's exactly what Laravel does

sinalco's avatar

@bestmomo and @usman

I don't want a "big custom service", that's the point; I have multiple dedicated service providers for each specific functionality (my package is kind of a core "platform" based on Laravel).

I can add all these providers one by one in the app.php file, and this would be the standard method; this is how the core Laravel providers are registered.

However, it would be nice to register only one service provider for my whole package instead of multiple, specific ones, so I could tell developers "add Acme\AcmeServiceProvider to the app providers" instead of "add Acme\AcmeServiceProvider1, then Acme\AcmeServiceProvider2, then another one, etc."

I can live with that, but if there is a better way, it would be great! ;-)

luddinus's avatar

@nmafurt I'm doing it in one application in a ServiceProvider called "CoreServiceProvider", I was wondering the same too so here I am.

michaeldyrynda's avatar

@nmarfurt - in a project that I'm working on I have a JmsServiceProvider (this is for my app, you can call it YourAppServiceProvider), which looks for and loads modules in a way I think will be similar to what you're after.

My directory structure (L4.2):

app
    Jms
        Composers
        Exceptions
        Libraries
        Modules
            Clients
                Controllers
                Handlers
                Models
                Repositories
                Validators
                routes.php
        Providers
            JmsServiceProvider.php

So in My JmsServiceProvider's register() method, I iterate through each of the modules and load each module's service provider, views, and routes files if they exist. The service provider for a module will exist in Modules/Providers/ModuleProvider.php

$directory = new \DirectoryIterator(dirname(__FILE__) . '/../Modules');

foreach ($directory as $info)
{
    if ( ! $info->isDot() )
    {
        $module = $info->getFilename();

        if ( is_readable($info->getPathname() . '/Providers/ModuleProvider.php') )
        {
            $this->app->register('Jms\Modules\\' . $module . '\Providers\ModuleProvider');
        }

        if ( is_dir($info->getPathname() . '/Views') )
        {
            $this->app->view->addLocation($info->getPathname() . '/Views');
        }

        if ( is_readable($info->getPathname() . '/routes.php') )
        {
            require $info->getPathname() . '/routes.php';
        }
    }
}

Any time I need to add a new module to the app (Contacts, Invoices, Jobs, for example), I just create the new directory structure. Then, given the Jms folder is namespaced using psr-0 (in my composer.json), everything loads nicely from within there.

3 likes
sinalco's avatar

@deringer Thanks for your input, that's actually close to the mechanism I did myself.

I was actually wondering if this approach (manually calling $this->app->register('Another\Service\Provider'); from a "main" service provider) may present issues, especially with deferred providers.

michaeldyrynda's avatar

I'm not sure about that @nmarfurt - the approach is the one I took with my app, where I didn't need deferred providers, so you'll have to do your own testing there. Even if the loading is deferred, I'm pretty sure you'll need to register the provider regardless, though.

Please or to participate in this conversation.