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

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.

Related

How to load, process and use custom parameters from Yaml configuration files in DI Extension class?

I'm trying to import a yaml configuration file in my App following the documentation provided here http://symfony.com/doc/current/bundles/extension.html but I always have the error message:
There is no extension able to load the configuration for "app"
My file is located here : config/packages/app.yaml and has the following structure :
app:
list:
model1:
prop1: value1
prop2: value2
model2:
...
As this is a simple App, all the files are in src/. So I have src/DependencyInjection/AppExtension.php
<?php
namespace App\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
class AppExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
}
}
And src/DependencyInjection/Configuration.php
<?php
namespace App\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');
// Node definition
$rootNode
->children()
->arrayNode('list')
->useAttributeAsKey('name')
->requiresAtLeastOneElement()
->prototype('array')
->children()
->requiresAtLeastOneElement()
->prototype('scalar')
->end()
->end()
->end()
->end()
->end();
return $treeBuilder;
}
}
I'm not able to access my parameters :(
Any idea?
If you want to load a custom configuration file to process it's parameters using an Extension class (like in Symfony bundle extension but without to create a bundle), to eventually "create" and add one or more of it to the "container" (before it will be compiled) you can register your Extension class manually in the configureContainer method contained in the Kernel.php file:
protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
{
// to avoid the same error you need to put this line at the top
// if your file is stored under "$this->getProjectDir().'/config'" directory
$container->registerExtension(new YourAppExtensionClass());
// ----- rest of the code
}
Then you can use your params as usual registering a Compiler Pass.
Hope this helps.

Dynamic database parameters file on 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 }

Dependency Injenction in config.yml

I have two services and I want pass my parameter from config.yml
my config.yml
parameters:
MyService.class: Acme\UserBundle\Services\sendEmail
MyService.arguments: #mailer
NewUserListener.class: Acme\UserBundle\Event\NewUserListener
NewUserListener.arguments: #MyService
my service.yml inside bundle
services:
MyService:
class: %MyService.class%
arguments: [%MyService.arguments%]
NewUserListener:
class: %NewUserListener.class%
arguments: [%NewUserListener.arguments%]
tags:
- { name: kernel.event_listener, event: new.user, method: sendEmailToUsers }
I got an error
You cannot dump a container with parameters that contain references to
other services
My Questions are:
How can I inject my arguments from config.yml?
Where can i Find the list of "global service" like #mailer ? i don't find in doc
You can't reference a service in a parameter. You should replace %MyService.arguments% with #mailer.
To find all available services, run php app/console container:debug
This a bit more complicated!
First, you have to declare your default services like that (I changed all the names in order to be compliant with the Symfony2's conventions):
# resources/config/services.yml
services:
my_own.service.default.class: Acme\UserBundle\Services\sendEmail
my_own.user_listener.default.class: Acme\UserBundle\Event\NewUserListener
services:
my_own.service.default:
class: %my_own.service.default.class%
arguments: [#mailer]
my_own.user_listener:
class: %my_own.user_listener.class%
arguments: [#my_own.service]
tags:
- { name: kernel.event_listener, event: new.user, method: sendEmailToUsers }
We will define some configuration for your bundle in order to allow to change the used services:
namespace My\OwnBundle\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
{
/**
* {#inheritDoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('my_own');
// Here you should define the parameters that are allowed to
// configure your bundle. See the documentation linked above for
// more information on that topic.
$rootNode
->children()
->scalarNode('service')->defaultValue('my_own.service.default')->end()
->scalarNode('user_listener')->defaultValue('my_own.user_listener.default')->end()
->end();
return $treeBuilder;
}
}
Note that, by default, we use our default services defined above in our bundle.
You now can use the following to change your services (in your app/config.yml) for instance:
# app/config.yml
my_own:
service: my_other.service
user_listener: my_other.user_listener
Of course, you can define the services my_other.service and my_other.user_listener as you want in your bundle or in another bundle.
Now we have to tell how to use this configuration to take the wanted services:
namespace My\OwnBundle\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 MyOwnExtension 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');
$container->setAlias('my_own.service', $config['service']);
$container->setAlias('my_own.user_listener', $config['user_listener']);
}
}
Finally, in the rest of your code you have to use the aliased services my_own.service and my_own.user_listener in your code:
// In one of your controller:
$this->container->get('my_own.service');
/* or directly */ $this->get('my_own.service'); // if your controller is a child of the framework bundle class `Controller`.

symfony2 DI bundle service unavailable

I've defined a service in the Resources/config/services.yml:
services:
gSm.gate.terminal:
class: Stream\TerminalBundle\StreamTerminal
arguments: [ [], [%terminal_login%, %terminal_password%] ]
And I try to access in inside my controller action:
public function displayAction() {
$terminal = $this->get('gSm.gate.terminal');
return $this->render('StreamTerminalBundle::display.html.twig');
}
Server returns following exception: 500 You have requested a non-existent service "gsm.gate.terminal". The bundle is registered in the appKernel, the bundle uses .yml config files... and I don't know what else can I look at to make this service available... thanks for any help.
EDIT:
My extension class code is:
namespace Stream\TerminalBundle\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 StreamTerminalExtension 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');
}
}
Make sure you're importing the bundle's services.yml. A simplest way is to import it from config.yml. A better and more advanced solution is to write an extension.
To see an example of an extension class, see my bundle's one. If you want to use YAML, just change services.xml to services.yml and XmlFileLoader to YamlFileLoader.
Is your services.yml file being parsed by the Extension class?
By default in a new bundle it's setup to load the xml file.
Can you paste your
Acme\Bundle\YourBundle\DependencyInjection\AcmeYourExtension
class?
I'm not sure you can use uppercase letters in you service names. The exception gives such a hint "gsm.gate.terminal" while your service is "gSm.gate.terminal".

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