Search code examples
phpsymfonybundle

Is there a way to share common package configuration across multiple symfony applications


I've tried searching across the documentation and symfony casts and looked in some of the major bundles and I've not seen anything quite right.

So where I work they follow a microservice architecture with dozens of small symfony applications. Common code is put into various seperate bundle/library repositories. So far all good.

However as the number of symfony applications grows keeping sensible logging configuration becomes more and more of a challenge and we find it tricky to keep the configuration in sync, some applications use the latest set of logging handlers and others are missing handlers or using older handlers. Each application has it's own ./config/package/monolog.yaml.

Is there a way to move this configuration from the symfony applications into a bundle lets call it ACMEBundle and have that configuration for monolog provided to all the symfony applications that use ACMEBundle. In the bundle could it still live in ./config/package/monolog.yaml or would it have to be elsewhere? Does the bundle library require any method or Extension class to ensure the configuration is registered in the symfony applications that use it?

The example I see are how to create bundles where the parent application service is then able to set configuration in the bundle. But instead I'm curious is it possible for an application to use a bundle that uses a bundle, where the middle bundle defines the configuration so the application doesn't have to.

In short: how can I get ACMEApplication[1,2,3,4,5] are symfony apps to use one ACMEBundle which defines package configuration for the MonologBundle.

Edit: would something like symfony flex work? although I'd rather a solution for the above that allow inherritance of configuration over a system that tries to keep configuration in sync.


Solution

  • You could use prepend extension, you can lighten the issue with the multiple bundles approach by using a single extension to prepend the settings for other bundles.

    It can use the settings defined in the config/* files to prepend settings just as if they had been written explicitly by the user in the application configuration.

    For example, this could be used to configure the entity manager name to use in multiple bundles. Or it can be used to enable an optional feature that depends on another bundle being loaded as well.

    So you can either have an extension that implements PrependExtensionInterface

    class YourExtension extends Extension implements PrependExtensionInterface
    

    Or use prependExtension in your bundle class (that inherit AbstractBundle)

    class YourBundle extends AbstractBundle
    

    You should check the documentation above, but it would look like:

    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
    use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
    
    class YourBundle extends AbstractBundle
    {
        public function prependExtension(ContainerConfigurator $containerConfigurator, ContainerBuilder $containerBuilder): void
        {
            // prepend
            $containerBuilder->prependExtensionConfig('monolog', [
                'setting' => ['foo' => 'bar'],
            ]);
    
            // prepend config from a file
            $containerConfigurator->import('../config/packages/monolog.php');
        }
    }