This tutorial is built using Symfony 4, but most of the concepts apply fine to Symfony 5!
// 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.21.6
"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
}
}
9 Comments
Hi,
There is a deprecation on the root node (<blockquote>@deprecated since Symfony 4.3, pass the root name to the constructor instead</blockquote>), it should be :
<br />$treeBuilder = new TreeBuilder('knpu_lorem_ipsum');<br />$rootNode = $treeBuilder->getRootNode();<br />Thanks for this great tutorial !
Pierre
Hi!
I should also change <i>"services.xml"</i> for everything to work. Namely - add 2
<argument />forunicorns_are_realandmin_sunshinerespectively. Without it I gotOutOfBoundsException: "Cannot replace arguments if none have been configured yet." (Symfony version - 5.2.1):Hi!
Tried to pass a Monolog alias as a parameter just to test if I was understanding everything and I got the error :
$definition->setArgument(0, $config['logger']);<blockquote>Argument 1 passed to TestBundle::__construct() must implement interface Psr\Log\LoggerInterface or be null, string given</blockquote>
I fiddled around for some time and solved it that way:
$definition->setArgument(0, $config['logger'] ? new Reference($config['logger']) : null);But is this canonical? It feels weird that in the config file the alias is not prefixed with an "@":
`
knpu_lorem_ipsum:
`
Thanks!
Edit: Okay so the next chapter kinda answers all that. Still confused about the fact that we don't need to use an "@" in the alias though.
Hey Renaud G.!
Yea, this whole "why do I need an @ here but not there" is a valid question. There is a perfectly logical reason... but it's still one of those things that you need to explain :p.
The reason is this: when you are defining a service (i.e. something under the
services:key), Symfony needed some way to differentiate between you setting an argument to the stringloggerand the servicelogger. Simple enough! We'll use@logger. So far so good, right :).Now that you're creating your shiny new bundle, you decide to add a
loggerkey (exactly like in your code above) and YOU (the bundle author) knows that this will be a service. So... why force the user to say@logger? If you did, you would be responsible to strip off the starting@so that you could create thenew Referencewithout it. And if the user did not include an@, you'd have to print an error like "Even though I know that what you are passing me is the id of a service, please put an@in front anyways".So... like I said, it's logical why bundle authors would not force an
@to be used... but it ultimately means that your config files look a bit inconsistent. Honestly, I hope that someday (it's possible now, just not the default), we'll use PHP for the services config, which doesn't need the@special symbol.Cheers!
Hi Ryan!
Thanks for your explanation, on point as usual!
If it really is an inconsistency, the Reference class constructor could take care of stripping the "@" only if present? Right now I'm doing ltrim($service_id, '@') so I can use both.
Also tried to use $container->getAlias($config['name']) but the alias for monolog was unlinkable for some reason. I guess it's not supposed to be used that way ^^
Hey Renaud G.!
> If it really is an inconsistency, the Reference class constructor could take care of stripping the "@" only if present? Right now I'm doing ltrim($service_id, '@') so I can use both.
You could definitely make this argument :).
> Also tried to use $container->getAlias($config['name']) but the alias for monolog was unlinkable for some reason. I guess it's not supposed to be used that way ^^
When you're in your *BundleExtension class, the ContainerBuilder that you're passed is an *empty* ContainerBuilder. This is done on purpose: Symfony is kind of "sandboxing" you: you can add services, etc, but you don't have access to read or change any services from any other bundles. When your method is done, Symfony merges your ContainerBuilder into the real one :). That's why you can't access other services or aliases. This is also done because if you *could* reference services/aliases from other bundles, ordering would be a mess: what if your bundle is (in some apps) loaded *before* MonologBundle? It keeps you away from that ugliness ;).
Cheers!
Hey Guys,
Great tutorial!
Just a quick one. Let's assume I did all the things correctly(however I am doing that in my own project) - is there any reason why config:dump would show me ~ instead of value for specific config?
I have one key in my config - name, which is a string. I have hooked up all of that as described and all works fine. However when I am trying to double check that on console I get this:
rob_simple_test:
name: ~
Instead of the value from config file. I know for a fact that value is in $config['name'] because I can see it there right before I go and do:
$definition->setArgument(0, $config['name']);
Do you Guys have at least an idea of what might be going on here?
Unicorns and rainbows on me for the one who solves that mistery!
Regards,
Rob
Hey Robert!
It sounds like you've got all the hard stuff set up. And... yea, I think I know the answer here :). There are 2 separate commands:
config:dumpReturns a YAML representation of all of the config keys and their default values by reading your Configuration object. This does not reflect your REAL config values in any waydebug:configReturns a YAML representation of the ACTUAL config values in your project (which is of course a combination of what you've configured plus any defaults from the Configuration classIn other words - this is expected! Just use debug:config instead - it should print what you're expecting.
Let me know if this answers your question! I gotta cash in on the unicorns and rainbows you promised ;).
Cheers!
Hey weaverryan !
That's it. You helped a lot. Thank you for this, now it's clear.
As for the Rainbows and Unicorns - is there any KnpU Mailbox to which I can send postcard full of those magnificent things?
"Houston: no signs of life"
Start the conversation!