I get following error:
There is no extension able to load the configuration for
"upload_images" (in
"/var/www/vhosts/diabetigraph-dev/vendor/verzeilberg/upload-images/src/Resources/services.yaml").
Looked for namespace "upload_images", found "none"
This are my files:
services.yaml
services:
verzeilberg\UploadImagesBundle\Service\Rotate:
autowire: true
upload_images:
version: 100
Configuration
namespace verzeilberg\UploadImagesBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('upload_images');
$treeBuilder->getRootNode()
->children()
->integerNode('version')->end()
->end();
return $treeBuilder;
}
}
UploadImagesExtension
namespace verzeilberg\UploadImagesBundle\DependencyInjection;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
class UploadImagesExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$loader = new YamlFileLoader($container, new FileLocator(dirname(__DIR__).'/Resources'));
$loader->load('services.yaml');
$config = $this->processConfiguration(new Configuration(), $configs);
$container->setParameter('version', $config['version']);
}
}
What am I doing wrong?
The basic answer is that your upload_images configuration needs to be moved to it's own application level config/packages file:
# app/config/packages/upload_images.yaml
upload_images:
version: 100
In your bundle, the Configuration object represents the bundle's configuration. There is no upload_images.yaml sort of file in your bundle. The object is quite powerful so you can add defaults and options and what not.
Your bundle's extension takes care of processing the final configuration and making information such as parameters available to the rest of the system:
class UploadImagesExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
// $configs is actually an array of array representing the contents of upload_files.yaml
$config = $this->processConfiguration(new Configuration(), $configs);
$container->setParameter('upload_files.version', $config['version']);
// Loading your bundle's services.yaml file is a different process which just happens to be kicked off by the loader
// Thanks to the setParameter above, %upload_files.version% can be used by services
$loader = new YamlFileLoader($container, new FileLocator(dirname(__DIR__).'/Resources'));
$loader->load('services.yaml');
}
}
It can be confusing and for me at least I had to read the docs multiple times and do quite a bit of experimenting to understand the overall process.
The confusion is one of the reasons that Symfony evolved from multiple bundles per application to one application bundle to no application bundle at all.
I might also add the Symfony uses composer recipes to simplify installing a bundle. The recipe not only adds the bundle to config/bundles.php but copies any default configuration file to config/packages as well. Unfortunately, there are additional steps required for this copy to happen (see the docs) so it's easiest to do things the old-fashion way and just tell the developer to create the config file via the bundle's README file.
Related
I'm trying to convert a bundle to symfony 4 and need to update my ancient parameters.yml to the modern symfony 4 way of life. Basicall the bundle itself - shared across multiple apps - should have a configurable file under /config/packages/.
However I receive this error:
(1/1) InvalidArgumentException
There is no extension able to load the configuration for "ptmr" (in /var/www/html/ptmr/pws_ptmrio_dev/PtmrBundle/DependencyInjection/../../config/packages/ptmr.yaml). Looked for namespace "ptmr", found none
/PtmrBundle/DependencyInjection/PtmrExtension.php
<?php
namespace PtmrBundle\DependencyInjection;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class PtmrExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration(true);
$config = $this->processConfiguration($configuration, $configs);
$loader = new YamlFileLoader(
$container,
new FileLocator(__DIR__ . '/../../config/packages')
);
$loader->load('ptmr.yaml');
}
}
/PtmrBundle/DependencyInjection/Configuration.php
<?php
namespace PtmrBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
private $debug;
public function __construct($debug = true)
{
$this->debug = (bool) $debug;
}
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('ptmr');
$treeBuilder->getRootNode()
->children()
->arrayNode('twitter')
->children()
->integerNode('client_id')->end()
->scalarNode('client_secret')->end()
->end()
->end() // twitter
->end()
;
return $treeBuilder;
}
}
/config/packages/ptmr.yaml
ptmr:
twitter:
client_id: 123
client_secret: your_secret
--
Note:
The Bundle itself works.
I added this line to psr-4 in composer.json:
"PtmrBundle\\": "PtmrBundle/"
This lines to config/routes/annotations.yml
ptmr_bundle:
resource: ../PtmrBundle/Controller/
type: annotation
These lines to config/services.yaml
services:
...
PtmrBundle\:
resource: '../PtmrBundle/*'
exclude: '../PtmrBundle/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
...
PtmrBundle\Controller\:
resource: '../PtmrBundle/Controller'
tags: ['controller.service_arguments']
And of course PtmrBundle/PtmrBundle.php
<?php
namespace PtmrBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class PtmrBundle extends Bundle
{
}
I'm following these instructions and I reaaaly do not see any errors. What am I missing? Symfony 4.2.
I found the answer after all. To make your own config/bundle.yaml parameters file, simply do:
Step 1: Create a file in your bundle DependencyInjection/{BundleNameWithoutBundle}Extension.php, e.g. for MyBundle > MyExtension.php
<?php
namespace MyBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
class MyExtension extends \Symfony\Component\DependencyInjection\Extension\Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$container->setParameter('my', $config);
}
}
Also see How to Load Service Configuration inside a Bundle
Step 2: Make a configuration file that provides a schema for your .yaml file DependencyInjection/Configuration.php
<?php
namespace MyBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('my');
$treeBuilder->getRootNode()
->children()
->variableNode('project_name')->end()
->end()
;
return $treeBuilder;
}
}
Also see How to Create Friendly Configuration for a Bundle
Step 3: Mirror the Configuration.php in your config/my.yaml
my:
project_name: "My Name"
Now the parameter my is available (set in MyExtension Class). Simply get it in your Controller like:
class IndexController extends AbstractController
{
public function indexAction(ParameterBagInterface $parameterBag)
{
...
dump($parameterBag->get('ptmr'));
return $this->render('index.html.twig');
}
}
Note: Most bundles go further and manipulate the bundles config xml files, which is out of scope for a simple question like this. A simple example on how to do this is the KnpPaginatorBundle which is not overly complicated to understand for settings parameters.
Personal Note: It seems to me, the Symfony docs are overly complicated and should provide a simple example. You got to know a lot of nomenclature and it's hard to learn it, especially compared to other well documented symfony chapters.
You are attempting to load configuration for your bundle before Symfony is aware of your bundle. Your bundle class must be loaded and configured before you can parse configuration under the ptmr property.
Typically your bundle would load __DIR__.'/../Resources/config/services.yaml which contains service and parameters definitions. Outside of your bundle, in your application config/ dir, you would then load configuration under the ptmr property.
I develop a little bundle, that provides tag cloud functionality. It should be easy, to include it in other Symfony projects and therefore it needs to be configurable. I discovered 3 pages:
How to Create Friendly Configuration for a Bundle
Defining and Processing Configuration Values
How to Load Service Configuration inside a Bundle
I worked along the examples, but it's obvious, that I miss something, because I get the following error message when I use php app/console config:dump-reference:
[Symfony\Component\Config\Exception\FileLoaderLoadException]
There is no extension able to load the configuration for "loew_tag" (in somePath/blog/app/config/../../src/Loew/TagBundle/Resources/config/config.yml). Looked for namespace "loew_tag", found " ... " in somePath/blog/app/config/../../src/Loew/TagBundle/Resources/config/config.yml (which is being imported from "somePath/blog/app/config/config.yml").
and
[Symfony\Component\DependencyInjection\Exception\InvalidArgumentException]
There is no extension able to load the configuration for "loew_tag" (in /home/somePath/blog/app/config/../../src/Loew/TagBundle/Resources/config/config.yml). Looked for namespace "loew_tag", found "framework", "security", "twig", "monolog", "swiftmailer", "assetic", "doctrine", "sensio_framework_extra", "blog", "fos_user", "debug", "web_profiler", "sensio_distribution"
I work inside a 'blog bundle' and try to access the config data for the 'tag bundle'.
Top of my 'app/config/config.yml':
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
- { resource: ../../src/Loew/TagBundle/Resources/config/services.yml }
- { resource: ../../src/Loew/TagBundle/Resources/config/config.yml }
LoewTagExtension.php:
<?php
// Loew/TagBundle/DependencyInjection/LoewTagExtension.php
namespace Loew\TagBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
class LoewTagExtension extends Extension
{
/**
* {#inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
//$container->setParameter('food_entities', $config['food_entities']);
$container->setParameter('split_match', $config['split_match']);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('config.yml');
$loader->load('services.yml');
}
}
config.yml:
loew_tag:
# food_entities:
# - "BlogBundle:Article"
# - "BlogBundle:Comment"
split_match: "/[^0-9a-zA-ZöÖüÜäÄß]/"
Configuration.php:
<?php
// Loew/TagBundle/DependencyInjection/Configuration.php
namespace Loew\TagBundle\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('loew_tag');
$rootNode
->children()
->scalarNode('split_match')->end()
// ->arrayNode('food_entities')
// ->prototype('scalar')->end()
->end();
return $treeBuilder;
}
}
Entries for the node food_entities are commented in all files to keep it as simple as possible.
I noticed, that similar questions has been asked and the regarding problems has been solved but I cannot transfer that solutions to this issue.
Any idea, what I do miss?
Finally solved this by
keeping naming conventions in mind, especially the part, pointed out by Jakub Zalas
removing entry: $loader->load('config.yml'); from the extension file.
Obviously, the config file will be loaded automatically as soon, as the service has been loaded.
I have a bundle which was working quite well for some time. However, I had to add some custom configuration params to it, so I wrote some lines in the bundle's config.yml, something like this:
# ...
acme_my_bundle:
special_params: ['param_1', 'param_2']
The configuration is defined in the bundle's Configuration class:
namespace ACME\MyBundle\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('acme_my_bundle');
$rootNode
->children()
->arrayNode('special_params')
->end()
->end();
return $treeBuilder;
}
}
The bundle is properly registered in AppKernel.php:
public function registerBundles() {
$bundles = array(
// ...
new ACME\MyBundle(),
// ...
);
// ...
return $bundles;
}
However, when I try to use my app, I get an error:
There is no extension able to load the configuration for "acme_my_bundle" (in (path_to_bundle)/MyBundle/DependencyInjection/../Resources/config/config.yml). Looked for namespace "acme_my_bundle", found none
I looked it up, but most results found were unsatisfactory - I eliminated the problems that came up during searching:
improper configuration structure
bundle not registered in the app kernel
config root node name different than the one returned from ACMEMyBundleExtension::getAlias()
I tried debugging the cause of the exception being thrown and discovered that when the YAML file loader tries to validate my config file, the container has no extensions:
var_dump($container->getExtensions()); // prints empty array - array(0) { }
It causes the validation to fail and the none part of the message to be displayed - there a no available extensions.
I tried debugging $this->extensions in ContainerBuilder::hasExtension() and for some reason the list is complete when the method is launched for the vendor bundles, but is empty for my bundle. It looks like that something in my bundle is still defined or registered incorrectly.
I changed the names off classes, etc. not to expose company code, excuse me for that if it causes confusion.
EDIT: I didn't explicitly mention it, but the Extension class is defined and the exception occurs when it is loaded - just as I have written above:
when the YAML file loader tries to validate my config file
To be more clear, here is my Extension class:
namespace ACME\MyBundle\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 ACMEMyBundleExtension 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'));
// The exception is thrown here
$loader->load('config.yml');
}
}
Check your configuration reader in ACME\MyBundle\DependencyInjection\Configuration for $rootNode = $treeBuilder->root('BUNDLE_CONFIG_KEY');.
BUNDLE_CONFIG_KEY should be:
valid (same in ACME\MyBundle\DependencyInjection\Configuration and your config.yml
unique for the app
Also please check you're defining bundle configuration in correct way - it should be added to app/config/*.yml (one of global config files). Maybe you have added acme_my_bundle config in other custom bundle config files?
You have missed bundle extension class (ACME\MyBundle\DependencyInjection\ACMEMyExtension) as explained here http://symfony.com/doc/current/cookbook/bundles/extension.html. Cookbook entry for bundle configuration is here. Key in config.yml should be named only as acme_my.
Creating the Configuration class alone is not enough. You need to register a dependency injection extension and use the Configuration class in there.
Read more about in the How to Create Friendly Configuration for a Bundle cookbook:
[The Configuration] class can now be used in your load() method to merge configurations and force validation (e.g. if an additional option was passed, an exception will be thrown)
namespace Acme\MyBundle\DependencyInjection;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class AcmeMyBundleExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
// ...
}
}
Naming your extension class according to the convention will make it's automatically loaded. More on creating DIC extension classes in Creating an Extension Class. You can also enable the extension manually, see Manually registering an extension class.
Iam trying to implement service for encoding password but it seems it doesn't work cause I get "You have requested a non-existent service user_service " error.
Here is my code :
Vendor/BundleNameBundle/Resources/config/services.yml
services:
user_service:
class: Morescreens\VideomanagerBundle\Service\UserService
arguments: ['#security.encoder_factory']
app/config/config.yml
imports:
- { resource: "#morescreensVideomanagerBundle/Resources/config/services.yml" }
code for my service
class UserService {
/**
* #var EncoderFactoryInterface
*/
private $encoderFactory;
public function __construct(EncoderFactoryInterface $encoderFactory)
{
$this->encoderFactory=$encoderFactory;
}
public function setEncodedPassword(User $user)
{
$encoder=$this->encoderFactory->getEncoder($user);
$password=$encoder->encodePassword($user->getPassword(),$user->getSalt());
$user->setPassword($password);
}
}
Inside mine controller:
$user=new User();
$user->setPassword('password');
$this->get('user_service')->setEncodedPassword($user);
EDIT:
I manually deleted cache folder and my service started to work.
Try looking at your src/{VendorName}/{BundleName}Bundle/DependencyInjection/{VendorName}{BundleName}Extension.php
This file should load your service definitions like this:
<?php
namespace Vendor\{BundleName}Bundle\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 Vendor{BundleName}Extension extends Extension
{
/**
* {#inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
//Load our YAML resources
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
}
}
This will load the service definition from src/{VendorName}/{BundleName}Bundle/Resources/config/services.yml into the container. If that still doesn't work try doing php app/console cache:clear. For speed reasons, symfony will basically aggregate all your service (and other configuration files) into a cached file so it doesn't have to read those files every time. The files that actually cache the service definitions are located:
app/cache/{envName}/ (The cache directory can be configured to be located wherever you want, this is just the default).
The files that have the relevent info for container service definitions are:
app{EnvName}DebugProjectContainer.php
app{EnvName}DebugProjectContainer.php.meta
app{EnvName}DebugProjectContainer.xml
I am trying to expose a custom configuration defined for my bundle which is called DecisionBundle.
I have a Decision\DecisionBundle\Resources\config\custom.yaml that looks like this:
decision:
testValue: 11
anotherTest: 12
I also have an Extension that looks like this:
namespace Decision\DecisionBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
class DecisionExtension 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');
$loader->load('custom.yml');
}
}
The file custom.yml seems to be loaded ok. Next comes the configuration interface
namespace Decision\DecisionBundle\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('decision');
$rootNode
->children()
->scalarNode('testValue')->defaultValue('0')->end()
->scalarNode('anotherTest')->defaultValue('0')->end()
->end();
// Here you should define the parameters that are allowed to
// configure your bundle. See the documentation linked above for
// more information on that topic.
return $treeBuilder;
}
}
However, this results in the following:
InvalidArgumentException: There is no extension able to load the configuration for "decision" (in *****\src\Decision\DecisionBundle\DependencyInjection/../Resources/config\custom.yml). Looked for namespace "decision", found none
Can somebody point me as to what I am doing wrong? Do I need to manually register the Extension somehow? However, the Extension seems taken into account as it looks loaded from the debug info.
Thanks!
Currently you are setting parameters in your custom.yml file in the same way that you would set them in the `app/config/config.yml' file.
decision:
testValue: 11
anotherTest: 12
When you are loading a file through the configuration file then your service files (services.yml & custom.yml in your case) should have either services or parameters as the headers. To use your parameters in the custom.yml file you should lay it out like..
parameters:
decision.testValue: 11
decision.anotherTest: 12
Also, if you are putting the parameters in the app/config/config.yml file, you need to set them to actual parameters in your DecisionExtension. To do this you would need to get the data from your Configuration file and set them in the container like..
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new
FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
$loader->load('custom.yml');
$container->setParameter('decision.testValue', $config['testValue']);
$container->setParameter('decision.anotherTest', $config['anotherTest']);
This, however, will overwrite the parameters set in your custom.yml and also negate any reason for it being there.