Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

All about the Bundle Extension Config System

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $8.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

We're not passing any arguments to the service... but this class does have two very important arguments: whether or not unicorns are real and the minimum times the word sunshine should appear in each paragraph. But what if a user of our bundle wants more sunshine or - gasp - they don't believe in unicorns? Right now, there's no way for them to control these arguments.

So if the bundle is responsible for registering the services & passing its arguments, how can the user of that bundle control those arguments? The answer lives in the config/packages directory.

Some important notes: first, our app automatically loads & processes all .yaml files it finds in this directory. Second, the names of these files are not important: you could rename them to anything else, .yaml. And third, the entire purpose of these files is to control the services that are provided by different bundles. When Symfony sees the framework key, it passes this configuration to the FrameworkBundle, which uses it to modify the services it provides.

The same for monolog: this config is passed to MonologBundle and it uses that when registering its services.

Creating a New Config File

Create a new file: knpu_lorem_ipsum.yaml - but, we could call this anything. And just to see what will happen, add some fake config: foo:, then bar: true.

foo:
bar: true

Find your browser and refresh! Error! Check out the language carefully. It says that there is no extension able to load the configuration for "foo". We know that word extension: we just created our own extension: KnpULoremIpsumExtension.

Then, since foo is apparently invalid, it lists a bunch of valid keys, like framework, web_server, twig, etc. Here's the deal: when Symfony sees a root key like framework, it looks at all of the bundles, well, really, the extension class for each bundle, to see if there is one called FrameworkExtension. If there is, it passes the config to it. If there is not, it throws this big, hairy, ugly exception.

Passing Config to our Extension

But check this out: go back to the list of valid keys. Thanks to our KnpULoremIpsumExtension class, there's one called knp_u_lorem_ipsum! Change the root key to use that instead.

knp_u_lorem_ipsum:
... lines 2 - 3

Next, open our extension class, var_dump($configs) and die.

... lines 1 - 9
class KnpULoremIpsumExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
var_dump($configs);die;
... lines 15 - 16
}
}

Try it out! No error! And cool! That bar: true value is passed to the load method! We're one step closer to using that config to tweak our service.

But, there are two weird things. First, the root key is... uh... not perfect. The knp_u_ is.. weird - I want it be knpu_... but apparently Symfony disagrees: our extra capital "U" is confusing things. We'll fix this in a bit.

The second weird thing is that the $configs value that's passed to load() is not just a simple array with bar=true. Nope, it's an array of arrays. Inception. Why? Well, it's possible that the user could add configuration for our bundle in multiple files. Like, we could have a dev environment-specific YAML file. When that happens, instead of merging that config together, it would pass us the configuration from both files. For example, if knp_u_lorem_ipsum existed in three different files, this array would have three different arrays inside. And, yep! It will be our job to merge them together. But, that's actually going to be really cool.

But before we do that, let's fix our alias to be knpu_lorem_ipsum. It's not something you often need to worry about, but the fix is super interesting.

Leave a comment!

7
Login or Register to join the conversation
Braunstetter Avatar
Braunstetter Avatar Braunstetter | posted 2 years ago

Hey Ryan!

I just used my extension to add a custom namespace to the twig bundle extension by finding this documentation article:

https://symfony.com/doc/cur...

That works!!! BUT .... If I am right - there is in the future no way for other bundles to extend the twig paths again. Because the documentation sais:


If there is more than one bundle that prepends the same extension and defines
the same key, the bundle that is registered first will take priority:
next bundles won’t override this specific config setting.

Is there a way - to like really overwrite the configuration of an extension from another bundle without obstructing a way for other bundles inside the symstem to do the same

Reply

Hey Michael B.

Probably using CompilerPass will give you more power to achive what you need!

Cheers!

1 Reply
Default user avatar
Default user avatar valentin thibault | posted 2 years ago

Hi,

How .yml file configuration can be generate automaticaly in config/packages ?

thanks for answer and tutorials.

Reply

Hi valentin thibault!

For that, you need to create a "recipe" for your package :). You do that by creating pull request to this repository - https://github.com/symfony/...

Let me know if you have any questions about that.

Cheers!

Reply
Default user avatar
Default user avatar valentin thibault | weaverryan | posted 2 years ago

Hi,
Thx for answer, it's helpful.
What if i want to have a local "recipe" ? Is it possible ?
My bundle is for my company projects, i can't publish it online.

Cheers!

Reply

Hey valentin thibault!

Ah! Unfortunately, that is not supported (there was BETA support for this, but it didn't get enough interest). There is one person that has built something to help with this - you could give it a try :) https://blog.mayflower.de/8...

Cheers!

Reply
Default user avatar
Default user avatar valentin thibault | weaverryan | posted 2 years ago

Thx a lot, i'll search for a solution ;)

Cheers !

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial is built using Symfony 4, but most of the concepts apply fine to Symfony 5!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "doctrine/annotations": "^1.8", // v1.8.0
        "knplabs/knp-markdown-bundle": "^1.7", // 1.7.0
        "knpuniversity/lorem-ipsum-bundle": "*@dev", // dev-master
        "nexylan/slack-bundle": "^2.0,<2.2", // v2.0.1
        "php-http/guzzle6-adapter": "^1.1", // v1.1.1
        "sensio/framework-extra-bundle": "^5.1", // v5.1.6
        "symfony/asset": "^4.0", // v4.0.6
        "symfony/console": "^4.0", // v4.0.6
        "symfony/flex": "^1.0", // v1.18.7
        "symfony/framework-bundle": "^4.0", // v4.0.6
        "symfony/lts": "^4@dev", // dev-master
        "symfony/twig-bundle": "^4.0", // v4.0.6
        "symfony/web-server-bundle": "^4.0", // v4.0.6
        "symfony/yaml": "^4.0", // v4.0.6
        "weaverryan_test/lorem-ipsum-bundle": "^1.0" // v1.0.0
    },
    "require-dev": {
        "easycorp/easy-log-handler": "^1.0.2", // v1.0.4
        "sensiolabs/security-checker": "^4.1", // v4.1.8
        "symfony/debug-bundle": "^3.3|^4.0", // v4.0.6
        "symfony/dotenv": "^4.0", // v4.0.6
        "symfony/maker-bundle": "^1.0", // v1.1.1
        "symfony/monolog-bundle": "^3.0", // v3.2.0
        "symfony/phpunit-bridge": "^3.3|^4.0", // v4.3.3
        "symfony/stopwatch": "^3.3|^4.0", // v4.0.6
        "symfony/var-dumper": "^3.3|^4.0", // v4.0.6
        "symfony/web-profiler-bundle": "^3.3|^4.0" // v4.0.6
    }
}
userVoice