I created a custom extension in my app for the sole purpose of being able to define config in yaml. I am unable to retrieve configuration params with ParameterBagInterface. What am I missing with the following approach?
config/packages/myapp.yaml
myapp:
foo:
bar: '%env(MYAPP_BAR)%'
I created a command to test if I could retrieve the config. When run, I get the error:
The parameter "myapp" must be defined.
class FooCommand extends Command
{
...
public function __construct(ParameterBagInterface $params, $name = '')
{
$this->params = $params;
parent::__construct();
}
...
protected function execute(InputInterface $input, OutputInterface $output): int
{
dd($this->params->get('myapp'));
...
I set all this up by creating the following files and modifying Kernel.php
src/DependencyInjection/Configuration.php
src/DependencyInjection/MyappExtension.php
Note that in the extension file below, the dd($config) prints everything defined in myapp.yaml.
src/DependencyInjection/MyappExtension.php
class MyappExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
// This dumps my config as an array
// dd($config);
}
}
src/DependencyInjection/Configuration.php
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('myapp');
$treeBuilder->getRootNode()
->children()
->arrayNode('foo')
->children()
->scalarNode('bar')->end()
->end()
->end()
->end();
return $treeBuilder;
}
src/Kernel.php (1 line modification)
...
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
{
$container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
$container->registerExtension(new MyappExtension());
...
Related
I'm trying to create a default configuration for my bundle. I created the bundle, bundle extension and configuration class. Inside the configuration class, I define a couple of keys with a default value. No yaml files are created. When I try to dump the configuration, I got the error:
"The extension with alias "foxtrot_alpha_users" does not have configuration."
But if I create the matching yaml file, and define at least one of the keys, the other key takes the default value as stated in the configuration class the value can be overridden.
Is it possible to define a default configuration with no yaml file at all?
Bundle class:
class UsersBundle extends Bundle
{
/**
* this is to have a custom alias
*
* #return void
*/
public function getContainerExtension()
{
return( new UsersExtension() );
}
}
Extension class:
class UsersExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
foreach($config as $key => $value)
{
$parameterKey = $this->getAlias().'.'.$key;
$container->setParameter($parameterKey, $value);
}
$container->setParameter('default_password', $config['default_password']);
}
/**
* customized alias
*
* #return string
*/
public function getAlias()
{
return('foxtrot_alpha_users');
}
Configuration class:
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('foxtrot_alpha_users');
$rootNode = $treeBuilder->getRootNode();
$this->addUserParameters( $rootNode );
return $treeBuilder;
}
private function addUserParameters( ArrayNodeDefinition $rootNode )
{
$rootNode
->addDefaultsIfNotSet()
->children()
->scalarNode('default_password')
->defaultValue('248')
->end()
->scalarNode('x')
->defaultValue('1')
->end()
->end()
;
return( $rootNode );
}
I'm running a website under Symfony 3.4.12 and I created my own custom bundle. I have a custom config file in Yaml :
# src/CompanyBundle//Resources/config/config.yml
company_bundle:
phone_number
... and it is launched this way :
<?php
# src/CompanyBundle/DependencyInjection/CompanyExtension.php
namespace CompanyBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
class CompanyExtension extends Extension
{
/**
* {#inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('config.yml');
}
}
?>
I would like to retrieve my custom parameters in my controller file, what is the best way to do it ? I tried this way, with no success :
$this->getParameter('company_bundle.phone_number')
Thanks.
You have to define your own DependencyInjection/Configuration.php: http://symfony.com/doc/3.4/bundles/configuration.html#processing-the-configs-array
Like that:
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('company_bundle');
$rootNode
->children()
->scalarNode('phone_number')
->end()
->end()
;
}
And then process it into your DependencyInjection/...Extension.php file. If you want to make this option as parameter you have to do it like that:
public function load(array $configs, ContainerBuilder $container)
{
// Some default code
$container->setParameter('company_bundle.phone_number', $config['phone_number']);
}
And then you can get this parameter in your controller like you do.
I try to prepend a config array to a different bundle using the prependExtensionConfig from my bundle. All works fine until $config is hardcoded.
My goal is to load the $config values using a service (from the db for example) and than prepend it to the other bundle.
The problem is that the services are not loaded at that moment.
I guess this is a limitation is symfony2.
Any ideas? thx
class MyExtension extends Extension implements PrependExtensionInterface
{
/**
* {#inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('services.yml');
}
public function prepend(ContainerBuilder $container)
{
$config = // load config from a service ...
$container->prependExtensionConfig('other_bundle', $config);
}
}
First of all you need to set up your config to take values from parameters section of Service container:
Setup config.yml:
# app/config/config.yml
namespace:
subnamespace:
param1: %param1%
param2: %param2%
Then you need to fill %param1% and %param2% parameters in container with values from database. To do that you need to declare your CompilerPass and add it to the container. After whole container will be loaded (in the compile time) you will have access to all services in it.
Just get the entity manager service and query for needed parameters and register them in container.
Define Compiler pass:
# src/Acme/YourBundle/DependencyInjection/Compiler/ParametersCompilerPass.php
class ParametersCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$em = $container->get('doctrine.orm.default_entity_manager');
$param1 = $em->getRepository('Acme:Params')->find(1);
$param2 = $em->getRepository('Acme:Params')->find(2);
$container->setParameter('param1', $param1);
$container->setParameter('param2', $param2);
}
}
In the bundle definition class you need to add compiler pass to your container
# src/Acme/YourBundle/AcmeYourBundle.php
class AcmeYourBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new ParametersCompilerPass(), PassConfig::TYPE_AFTER_REMOVING);
}
}
PassConfig::TYPE_AFTER_REMOVING means that this CompilerPass will be processed almost after all other compiler passes and in this moment you will already have every service injected.
I need to get some data in my db and the current user, so I use the entity manager and security.context in my service
I have this error :
Fatal error: Call to a member function getRepository() on a non-object
in path/to/file on line 84
service.yml :
services:
ns_messagerie.letterboxcore:
class: ns\MessagerieBundle\LetterBoxCore\LetterBoxCore
arguments: [#security.context, #doctrine.orm.entity_manager]
Dependency injection :
class nsMessagerieExtension extends Extension
{
/**
* {#inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
}
}
And my service :
class LetterBoxCore {
protected $securityContext;
protected $em;
public function __construct( $securityContext, $entityManager) {
$this->securityContext = $securityContext;
$this->em = $entityManager;
}
public function countNbNotRead(Utilisateur $user = null, Discussion $discussions) {
//...
}
public function getAllDiscussion(Utilisateur $user = null, $all = null) {
// line 84:
$list = $em->getRepository('nsMessagerieBundle:ParticipantMessagerie')
->findBy(array('participant' => $user,
'supprimer' => $all
)
);
}
public function getBAL(Utilisateur $user = null) {
// Call the method countNbNotRead and GetAllDiscussion
}
I have successfully installed the sncRedisBundle and used the predis element of it within a controller, using:
$this->container->get('snc_redis.default');
I want to do the same within an extension:
class MyExtension extends Extension
{
/**
* {#inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$redis = $container->get('snc_redis.default');
}
}
But I get:
The service definition "snc_redis.default" does not exist.
Is this a scoping issue? How do I access redis from within an Extension?
Thanks!
services:
site:
class: Emlaktown\AppBundle\Site\Site
arguments: [%api_url%, "#request_stack", "#service_container"]
....
use Symfony\Component\DependencyInjection\Container;
....
public function __construct($apiUrl, RequestStack $requestStack, Container $container)
{
$this->client = new Client($apiUrl);
$this->redis = $container->get('snc_redis.cache');
$request = $requestStack->getCurrentRequest();
$this->client->setDefaultOption('Accept-Language', $request->getLocale());
}