Symfony 5.1 service registration depending on database data

I’m using Symfony 5.1 and want to build a plugin system for my application.
The code of core application is placed in the src/ directory, the plugins will be stores in the custom/ directory.

The structure for a plugin is predefined and looks like this:

custom
|--SomePlugin
  |--Controller
  |--Subscriber
  |--...
  |--SomePlugin.php

There is also a database with a table that contains the status of the plugin, whether it is active or not.

| name   | version | status |
| ------ | ------- | ------ |
| string | string  | bool   |

How to load services from plugin namespaces

My application is already be setup to load services from the default App namespace – also controllers are loaded automatically. Since loading of those services and controllers depends on the status received from the database, I used the following customization of the Kernel.

// src/Kernel.php

namespace App;

class Kernel extends BaseKernel
{
    use MicroKernelTrait;

    // ...

    protected function configureRoutes(RoutingConfigurator $routes): void
    {
        $activePlugins = $this->getActivePlugins();

        $customDirectories = scandir($this->getProjectDir() . '/custom/');

        foreach ($customDirectories as $customDirectory) {
            if (!in_array($customDirectory, ['.', '..']) &&
                is_dir($this->getProjectDir() . '/custom/' . $customDirectory . '/Controller/')) {

                $prefix = call_user_func([$customDirectory . '' . $customDirectory, 'name']);
                $prefix = preg_replace('/[^a-z0-9]/i', '-', $prefix);
                $prefix = strtolower($prefix);

                if(in_array($prefix, $activePlugins)) {
                    $routes->import('../custom/' . $customDirectory . '/Controller/', 'annotation')
                        ->namePrefix($prefix . '_');
                }
            }
        }
    }

    // ...
}

The getActivePlugins() function returns an array with all active plugins. If a plugin is active, the route should be registers. This works fine.

But… to configure the services, I have to use the configureContainer() function.

// src/Kernel.php

// ...

protected function configureContainer(ContainerConfigurator $container): void
{
   $activePlugins = $this->getActivePlugins();

   // ...
}

// ...

The problem is: at this time the kernel is not booted, so the getActivePlugins() function has no access to the container and I cannot use Doctrine to fetch the data from the database.

Is there a way to register the services after the kernel is booted?

Source: Symfony Questions

Was this helpful?

0 / 0

Leave a Reply 0

Your email address will not be published. Required fields are marked *