Issue
I have created a Symfony 5.3+ bundle which should be used to add common code to different projects. The bundle contains some services which should be configurable using parameters / options as described in the Symfony docs.
How to provide default values for these options? Defaults set in the bundles Configuration.php
do not have any effect.
Details:
I have created a bundle project using the following structure and added it to my Symfony project using composer:
path/to/bundles/XYCommonsBundle/
config/
services.yaml
src/
Service/
SomeService.php
DependencyInjection
Configuration.php
XYCommensExtension.php
XYCommensBundle.php
composer.json
...
// src/DependencyInjection/XYCommensExtension.php
<?php
namespace XY\CommensBundle\DependencyInjection;
use ...
class XYCommensExtension extends Extension {
public function load(array $configs, ContainerBuilder $container) {
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
// make config available as parameters. Necessary?
foreach ($config as $key => $value) {
$container->setParameter('xy_commons.' . $key, $value);
}
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../../config'));
$loader->load('services.yaml');
}
}
// src/DependencyInjection/Configuration.php
class Configuration implements ConfigurationInterface {
public function getConfigTreeBuilder() {
$treeBuilder = new TreeBuilder('xy_commons');
$treeBuilder->getRootNode()
->children()
->arrayNode('params')
->children()
->integerNode('paramA')->defaultValue(100)->end()
->integerNode('ParamB')->defaultValue(200)->end()
->end()
->end()
->end()
;
return $treeBuilder;
}
}
// config/services.yaml
services:
xy_commons.service.some_service:
class: XY\CommonsBundle\Service\SomeService
arguments:
- $paramA: '%xy_commons.params.paramA%'
- $paramB: '%xy_commons.params.paramB%'
// src/Service/SomeService.php
<?php
namespace XY\CommensBundle\Service;
use ...
class SomeService {
public function __construct(LoggerInterface $logger, $paramA, $paramB) {
}
Problem: How to use default values of parameters?
paramA
and paramB
are defined in the bundles Configuration.php
with default values of 100 and 200. I would like to use these defaults in the project without specifying custom values. However, I do not create a config/packages/xy_commons.yaml
file in the project and explicitly specify values, I get the following error:
You have requested a non-existent parameter "xy_commons.params.paramA".
When creating a config/packages/xy_commons.yaml
file, I cannot use ~
to use the default value:
xy_commons:
params:
paramA: ~
paramB: ~
Invalid type for path "xy_commons.params.paramA". Expected "int", but got "null".
Only when explicitly specifying a value it works:
xy_commons:
params:
paramA: 300
paramB: 400
How to use the default values defined in Configuration.php
?
Solution
There are three problems here. The first deals with what is possibly my least favorite class in Symfony. The dreaded configuration object. In particular, you need to use addDefaultsIfNotSet when dealing with arrays:
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('my');
$rootNode = $treeBuilder->getRootNode();
$rootNode
->children()
->arrayNode('params')->addDefaultsIfNotSet() # ADD THIS
->children()
->integerNode('paramA')->defaultValue(100)->end()
->integerNode('paramB')->defaultValue(200)->end()
->end()
->end()
->end()
;
return $treeBuilder;
}
}
The second problem is that you are not defining your parameters correctly. In particular the parameters will be grouped in an array called params. You almost had it:
class MyExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
foreach($config['params'] as $key => $value) {
$container->setParameter('xy_commons.params.' . $key, $value);
}
# Use bin/console dump:container --parameters to verify
The final thing is the use of tilde to indicate default values. I think this might be a works as designed issue. Technically, tilde on yaml means null and it is up to the processor to get it a meaning. The ArrayNode works as expected but the IntegerNode does not. So this works:
# config/packages/my.yaml
my:
params: ~
# paramA: ~
# paramB: 666
Answered By - Cerad Answer Checked By - David Marino (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.