If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeWhen you create an extension class, Symfony automatically calculates a "root" config key for it. In our case, it calculated knp_u_lorem_ipsum
... it generated this based on our class name. I'd rather have knpu_lorem_ipsum
. But of course, that doesn't work... yet.
This root key is called the extension alias. And we can totally control it. How? In our extension class, go to the Code->Generate menu, or Cmd+N on a mac, select "Override" methods, and choose getAlias()
. Then, return knpu_lorem_ipsum
.
... lines 1 - 9 | |
class KnpULoremIpsumExtension extends Extension | |
{ | |
... lines 12 - 18 | |
public function getAlias() | |
{ | |
return 'knpu_lorem_ipsum'; | |
} | |
} |
Here's how things really work. When Symfony boots, it loops over all the extension classes in the system, calls getAlias()
on each, and this becomes their config key. In the parent class, well, the parent's parent class, there is a default getAlias()
method which... surprise! Removes the Extension
suffix, and "underscores" what's left.
Cool! Easy fix! Find your browser and refresh to celebrate! Boo! Another error:
Users will expect the alias of the default extension of a bundle to be the underscored version of the bundle name. You can override some method if you want to use another alias.
Ok. This is a bit odd, but, on the bright side, it'll give us a chance to do some exploring! Open up our bundle class. It's empty... but it actually does a bunch of cool things. Hold Command or Ctrl and click to open the base class. One of the methods is called getContainerExtension()
.
When Symfony builds the container, it loops over all bundle classes and calls this method, which returns the extension object. Check out the createContainerExtension()
method, well, actually, the getContainerExtensionClass()
method. Ah! This is the reason why Symfony expects our extension to live in the DependencyInjection
directory and to end in the word Extension
. All that magic comes from overrideable methods on our bundle class.
Scroll back up to getContainerExtension()
. After it creates the container extension, it does a sanity check: if the alias is different than it expected, it throws an exception. This was originally added to prevent bundle authors from going crazy and creating custom aliases like delicious_pizza
or beam_me_up_scotty
.
But, it's kind of annoying. The fix is easy. In our bundle class, go to the Code -> Generate menu, or Cmd + N on a Mac, select Override Methods and choose getContainerExtension
.
Then, if null === $this->extension
, set $this->extension
to a new KnpULoremIpsumExtension
. Return $this->extension
at the bottom.
... lines 1 - 7 | |
class KnpULoremIpsumBundle extends Bundle | |
{ | |
/** | |
* Overridden to allow for the custom extension alias. | |
*/ | |
public function getContainerExtension() | |
{ | |
if (null === $this->extension) { | |
$this->extension = new KnpULoremIpsumExtension(); | |
} | |
return $this->extension; | |
} | |
} |
This does the same thing as the parent method, but without that sanity check.
Let's do it... refresh! Our custom alias is alive!!!
Now, it's time to use this $configs
array to start allowing our end-users to modify our service. This is one of my favorite parts.
Hey Ahmed,
Hm, probably the question is why do you need to register an extension? Probably you don't actually need it. If you want to import some services - import it manually in config/services.yaml, etc. But if you really need it and you 100% sure you can't avoid without it (I mean you can't implement what you want in a different way without registering an extension), you probably need to create an bundle class (e.g. AppBundle) which extends the base Bundle class, add it to config/bundles.php and manually register an extension class like showed in docs: https://symfony.com/doc/mas...
Cheers!
I just noticed that 11 users liked my comment, so that's why I'm going to propose a solution for the problem : Manually Registering an Extension Class, between us I had already file two solutions for a long time in tmy blog, (a French article), here a link for people who understands the language https://ahmedbhs.me/creation-dune-extension-di-dependency-injection-extensions ...
Ok so under AppKernel.php
class, it was necessary to add manually the extension with the function addExtension()
:
class AppKernel extends Kernel
{
...
protected function build(ContainerBuilder $container)
{
$container->registerExtension(new \AppBundle\DependencyInjection\AppExtension());
}
}
Great solution! Thanks for sharing! It’s indeed interesting to see what comments / questions get upvoted :)
Thank you for all the tutorials and availability, I really appreciate it. Anyway I think my way is a little hard coded and it should extend the getContainerExtension function as it is mentioned in the official doc and as Victor answered us. Besides it's because of his answer that I had the motivation to write the solution. Cheers!
Your solution is actually great - the BEST solution! In Symfony 4, because we don't have bundles (and you don't need them), what you showed IS the best solution.
By the way, what is your motivation for creating & registering an extension class? I'd like to hear the use-case that you (and apparently many other people) are having.
Cheers!
I understand you try to spicy things up when explaining.. but after 200 videos the "ahhh" and "ohh error" and "I l love errors" becomes annoying to listen to. It's like it breaks up the flow of words.
Hey Stefan D.!
Haha, fair enough :). I *do* like to show errors... so that you know what they mean when you hit them... and also, sometimes... it's on accident ;). But, it's funny - I have to listen to myself over and over again too for recording purposes - a person can only take so much Ryan :D
I hope you'll watch 200 more despite... and that's an impressive number - congrats!
// 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
}
}
I'm working with sf 3.4.9, trying to register an extension like mentioned in the doc https://symfony.com/doc/3.4...
But unfortunately my Extension class is not registered because I dont have the Bundle structure in my project, so any idea !!