Dynamic database parameters file on Symfony - symfony

I'm new to Symfony and i'm trying to load different parameters.yml depending on host, including database configuration. So, in apache vhosts, I defined a variable that let me know what client is in PHP by $_SERVER["CLIENTID"] ( Directive SetEnv ). And now I want to, for example if CLIENTID is "client1", load parameters_client1.yml, that contains db_host, db_user, etc...
I tried this way :
app/config/config.yml
doctrine:
dbal:
host: "%db_host%"
dbname: "%db_name%"
user: "%db_user%"
password: "%db_password%"
app/config/parameters_client1.yml
parameters:
db_host: "localhost"
db_name: "client1_database"
db_user: "client1"
db_password: "something"
src/AppBundle/DependencyInjection/Configuration.php
namespace AppBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('appbundle');
return $treeBuilder;
}
}
src/AppBundle/DependencyInjection/AppExtension.php
namespace AppBundle\DependencyInjection;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
class AppExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$rootdir = $container->getParameter('kernel.root_dir');
// Load the bundle's services.yml
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
// Load parameters depending on current host
$paramLoader = new Loader\YamlFileLoader($container, new FileLocator($rootdir.'/config')); // Access the root config directory
$parameters = "parameters.yml";
if( array_key_exists("CLIENTID", $_SERVER) )
{
$paramfile = sprintf('parameters_%s.yml', $_SERVER["CLIENTID"]);
if (file_exists($rootdir.'/config/'.$paramfile))
{
$parameters = $paramfile;
}
}
$paramLoader->load($parameters);
}
}
But that's not working, I got the following error :
ParameterNotFoundException in ParameterBag.php line 100:
You have requested a non-existent parameter "db_host".
Please can somebody explain me what I've missed ?
I'm using Symfony 3.2

A rough guess are you including the resource in app/config/config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }

Related

Symfony - There is no extension able to load the configuration - custom config

Helo,
i am trying to load custom config into my AppBundle. Unluckily I am getting:
[Symfony\Component\DependencyInjection\Exception\InvalidArgumentException]
There is no extension able to load the configuration for "app" (in
/var/www
/dev.investmentopportunities.pl/src/AppBundle/DependencyInjection/../Resour
ces/config/general.yml). Looked for namespace "app", found none
There are several similar topics relating to this error. I have looked at them but can't find any solution which would resolve this issue.
My configuration file looks like this:
<?php
namespace AppBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('app');
$rootNode
->children()
->arrayNode('tags')
->prototype('array')
->children()
->scalarNode('name')->isRequired()->end()
->scalarNode('role')->isRequired()->end()
->scalarNode('priority')->isRequired()->end()
->scalarNode('label')->isRequired()->end()
->end()
->end();
return $treeBuilder;
}
}
and general.yml:
app:
tags:
Accepted:
name: "Accepted"
role: "ROLE_ACCEPTTAG"
priority: "3"
label: "label label-info"
Booked:
name: "Booked"
role: "ROLE_ACCOUNTANT"
priority: "3"
label: "label label-info"
Finalized:
name: "Booked"
role: "ROLE_ACCEPTDOC"
priority: "1"
label: "label label-success"
AppExtension.php:
<?php
namespace AppBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\Validator\Tests\Fixtures\Entity;
/**
* This is the class that loads and manages your bundle configuration
*/
class AppExtension extends Extension
{
/**
* {#inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$container->setParameter('app', $config['app']);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('general.yml'); # another file of yours
}
}
TL;DR: You should not load your general.yml file in the extension.
Defining a configuration for a bundle is about how the bundle will handle configuration, understand the configuration coming from config.yml.
So you should import your general.yml file in the config.yml and it should work.
Note: Loaders are from Symfony\Component\DependencyInjection\Loader namespace, they are for dependency injection, to allow a bundle to define services, mostly used by third-party bundles.

How to debug ParameterNotFoundException in Symfony2

I'm getting the following error after following and adapting this
ParameterNotFoundException: You have requested a non-existent parameter "mynamespace_admin.amazon_s3.aws_key". Did you mean this: "mynamespace_admin.amazon_s3.class"?
In config.yml I have:
mynamespace_admin:
amazon_s3:
aws_key: %amazon_aws_key%
aws_secret_key: %amazon_aws_secret_key%
base_url: %amazon_s3_base_url%
And in my parameters.yml I have:
amazon_aws_key: ###
amazon_aws_secret_key: ###
amazon_s3_base_url: ###
amazon_s3_bucket_name: ###
And in services.yml:
parameters:
mynamespace_admin.amazon_s3.class: AmazonS3
mynamespace_admin.image_uploader.class: mynamespace\Bundle\AdminBundle\Uploader\ImageUploader
mynamespace_admin:
amazon_s3:
class: %mynamespace_admin.amazon_s3.class%
arguments:
- "%mynamespace_admin.amazon_s3.aws_key%"
- "%mynamespace_admin.amazon_s3.aws_secret_key%"
image_uploader:
class: mynamespace_admin.image_uploader.class%
arguments: [image_storage_filesystem]
Can anyone see what I have configured incorrectly or advise on how to debug this? Why can't mynamespace_admin.amazon_s3.aws_key be read from config.yml?
If things are not listed under the parameters key in the service configuration, it is not assumed it is a parameter.
In all other cases (except from the services key), it is assumed that it is the configuration for an extension. In this case, the extension called mynamespace_admin. That extension should parse the settings and maybe put them in the container as parameters, or use them to decide which files to include, etc.
Assume you have a correct Configuration class for the config you have given, your extension will look like this if you want to use the config as parameters:
// ...
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
class MynamespaceAdminExtension extends Extension
{
/**
* {#inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
// ... do some other stuff, like loading service definition files
// loop through the processed config and save them as parameters
foreach ($config['amazon_s3'] as $name => $value) {
$container->setParameter('mynamespace_admin.amazon_s3.'.$name, $value);
}
}
}

How can I listen to console events in symfony?

I'm trying to hook into symfonys console events with the symfony standard edition (2.3), but it just won't work.
I created a listener according to their example and follow the guides on event registration:
namespace Acme\DemoBundle\EventListener;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\ConsoleEvents;
class AcmeCommandListener
{
public function onConsoleCommand(ConsoleCommandEvent $event) {
// get the output instance
$output = $event->getOutput();
// get the command to be executed
$command = $event->getCommand();
// write something about the command
$output->writeln(sprintf('Before running command <info>%s</info>', $command->getName()));
}
}
and someone on the mailing list told me to register it as event in the service container. So I did this:
services:
kernel.listener.command_dispatch:
class: Acme\DemoBundle\EventListener\AcmeCommandListener
tags:
- { name: kernel.event_listener, event: console.command }
But obviously the tagging is not correct and I can't find the correct names for that. How would I do that?
Platform\EventListener\Console\InitListener:
tags:
- { name: kernel.event_listener, event: console.command, priority: 1024 }
<?php
class CustomListener
{
public function onConsoleCommand(ConsoleCommandEvent $event): void
{
//do somehting
}
}
?>
So, I finally got it. The above code in the original post ist fully working, but I defined my services.yml within my bundle not in the application config app/config.yml. This means, the configuration was never loaded. I had to import the configuration via container extensions:
# Acme/DemoBundle/DependencyInjection/AcmeDemoExtension.php
namespace Acme\DemoBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
class AcmeDemoExtension extends Extension
{
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
# Acme/DemoBundle/DependencyInjection/Configuration.php
namespace Acme\DemoBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('headwork_legacy');
return $treeBuilder;
}
}
Though I guess you can even leave out the $configuration = new Configuration(); part and the Configuration class.
Your tags event listener name must be a console.event_listener. It's has helped me to resolve this issue.
services:
kernel.listener.command_dispatch:
class: Acme\DemoBundle\EventListener\AcmeCommandListener
tags:
- { name: console.event_listener, event: console.command }

There is no extension able to load the configuration for "facebookbundle" symfony2

I create my own FacebookBundle and
I got this error:
There is no extension able to load the configuration for
"facebookbundle" (in /facebookx/app/config/config_dev.yml). Looked for
namespace "facebookbundle", found "framework", "security", "twig",
"monolog", "swiftmailer", "assetic", "doctrine",
"sensio_framework_extra", "jms_aop", "jms_di_extra",
"jms_security_extra", "d_facebook", "d_user", "d_security",
"web_profiler", "sensio_distribution"
The error message means that I got an entry "facebookbundle" in My config.yml which is not used by any extension ?
My config.yml
facebookbundle:
file: %kernel.root_dir%/../src/FacebookBundle/Facebook/FacebookInit.php
alias: facebook
app_id: xxx
secret: xxx
cookie: true
permissions: [email, user_birthday, user_location, user_about_me]
My DFacebookExtension
<?php
namespace D\FacebookBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
/**
* This is the class that loads and manages your bundle configuration
*
* To learn more see {#link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/
class DFacebookExtension 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');
foreach (array('app_id', 'secret', 'cookie', 'permissions') as $attribute) {
$container->setParameter('facebookbundle.'.$attribute, $config[$attribute]);
}
if (isset($config['file']) && $container->hasDefinition('acebookbundle.api')) {
$facebookApi = $container->getDefinition('facebookbundle.api');
$facebookApi->setFile($config['file']);
}
}
}
were is error ?
Also, keep in mind that the root key of the configuration file must be a normalized form of the Bundle's name.
This is something I've encoutered a few times and it's very frustrating to solve if you're not aware of it.
Example: if bundle is called MyFirstAwesomeBundle, then the root key in the file must be my_first_awesome. So camel-case is converted to snake-case and the word "bundle" is ignored or stripped away.
So simply having the root key in your file match exactly the value specified in Configuration::getConfigTreeBuilder() is not enough.
If you don't follow this rule, then you'll get the There is no extension able to load the configuration error.
I hope this will help the next desperate soul who ends up on this page...
In order for custom config parameters to be accepted you have to define your bundle configuration using a Configuration.php class within your bundle.
src/FacebookBundle/DependencyInjection/Configuration.php:
<?php
namespace FacebookBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* This is the class that validates and merges configuration from your app/config files
*
* To learn more see {#link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
*/
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('facebookbundle');
$rootNode
->children()
->scalarNode('file')->defaultValue('')->end()
->scalarNode('alias')->defaultValue('')->end()
->scalarNode('app_id')->defaultValue('')->end()
->scalarNode('secret')->defaultValue('')->end()
->booleanNode('cookie')->defaultTrue()->end()
->arrayNode('permissions')
->canBeUnset()->prototype('scalar')->end()->end()
->end()
;
return $treeBuilder;
}
}
?>
This happens when you forget to start the bundle in app/AppKernel.php :
<?php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = array (
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Symfony\Bundle\DoctrineBundle\DoctrineBundle(),
new Symfony\Bundle\AsseticBundle\AsseticBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),
//...
new D\FacebookBundle\DFacebookBundle(),
//...
);
if (in_array($this->getEnvironment(), array ('dev', 'test')))
{
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
}
return $bundles;
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__ . '/config/config_' . $this->getEnvironment() . '.yml');
}
}
This error can also be caused by a missing or invalid services key at the root of your config. It should look something like this:
services:
foo_bar.baz:
class: Foo\BarBundle\Service\BazService

overriding registration FOSUserBundle Symfony2

I am trying to override Registration Form in FOSUserBundle but i get this error:
i have followed this tutorial in the official documentation:
Link
Could not load type "uae_user_registration"
My files are:
services.yml
# src/Uae/UserBundle/Resources/config/services.yml
services:
uae_user.registration.form.type:
class: Uae\UserBundle\Form\Type\RegistrationFormType
arguments: [%fos_user.model.user.class%]
tags:
- { name: form.type, alias: uae_user_registration }
config.yml:
app/config/config.yml
fos_user:
db_driver: orm
firewall_name: main
user_class: Uae\UserBundle\Entity\User
registration:
form:
type: uae_user_registration
RegistrationFormType:
<?php
#src/Uae/UserBundle/Form/Type/RegistrationType.php
namespace Uae\UserBundle\Form\Type;
use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
class RegistrationFormType extends BaseType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
// add your custom field
$builder->add('nom');
$builder->add('prenom');
}
public function getName()
{
return 'uae_user_registration';
}
}
i solved my problem:
i just imported the new service that i created in the config file
app\config\config.yml
imports:
- { resource: #UaeUserBundle/Resources/config/services.yml }
The reason you're getting the error is because you do not have a DependencyInjection for your specific bundle. The program doesn't know where to look for your services.yml file.
You need an UaeUserExtension.php and Configuration.php inside your DependencyInjection folder under your User Bundle.
The easy solution to this is to generate the bundle via app/console generate:bundle. This way, it'll create your DependencyInjection for you automatically.
The manual solution would be to create a DependencyInjection folder inside your Uae/UserBundle. Inside DependencyInjection, create a file called Configuration.php and place the contents below:
<?php
namespace Uae\UserBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
/**
* {#inheritDoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('uae_user');
return $treeBuilder;
}
}
And create a file called UaeUserExtension.php inside the same directory and place these contents inside:
<?php
namespace Uae\UserBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
class EnergyUserExtension 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');
}
}

Resources