【问题标题】:"No extension able to load"“无法加载扩展”
【发布时间】:2016-04-26 18:32:04
【问题描述】:

我想在我的 AppBundle 中添加一个配置条目(使用 Symfony 3.0.3)。

我坚持的是:

尽管我努力尝试坚持文档示例并寻找有关 SO 的修复程序,但我仍然收到以下异常并且无法发现问题所在。

YamlFileLoader.php 第 368 行中的 InvalidArgumentException:
没有扩展能够加载“app”的配置 (在 /.../src/AppBundle/DependencyInjection /../Resources/config/config.yml)。寻找命名空间“app”,没有找到

存在线程/文章,但没有建议的解决方案实际上为我修复了它。有些细节可能一目了然,我希望有人能在我花费数小时的时候立即发现这些。


到目前为止我做了什么:

我首先设置了这个 conf 文件
我猜“app”键应该没问题,因为doc 期望名称是小写的包名称,其中 bundle 部分被剥离。对吧?

# AppBundle/Resources/config/config.yml
app:
    paginator:
        items_per_page: 3

然后我在 DependencyInjection 命名空间内设置加载/设置过程所需的 php 类...

配置类文件:

# /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('app');

        $rootNode
            ->children()
                ->arrayNode('paginator')
                    ->performNoDeepMerging()
                    ->addDefaultsIfNotSet()
                    ->children()
                        ->integerNode('items_per_page')
                            ->defaultValue(5)
                            ->isRequired()
                            ->cannotBeEmpty()
                        ->end()
                    ->end()
                ->end()
            ->end();
        return $treeBuilder;
    }
}

扩展类文件:
相应地命名为doc

# /src/AppBundle/DependencyInjection/AppExtension.php
namespace AppBundle\DependencyInjection;

use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\ContainerBuilder;

use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\Config\FileLocator;

class AppExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {

        $loader = new YamlFileLoader(
            $container,
            new FileLocator(__DIR__.'/../Resources/config')
        );

        $loader->load('config.yml');

        $processor     = new Processor();
        $configuration = new Configuration();
        $config = $processor->processConfiguration($configuration, $configs);

    }
}

堆栈跟踪

in YamlFileLoader.php line 368
at YamlFileLoader->validate(array('app' => array('paginator' => array('items_per_page' => '3'), 'mailer' => array('sender_name' => 'no-reply', 'sender_address' => '%mailer_user%'))), '/../project/src/AppBundle/DependencyInjection/../Resources/config/config.yml') in YamlFileLoader.php line 338
at YamlFileLoader->loadFile('/../project/src/AppBundle/DependencyInjection/../Resources/config/config.yml') in YamlFileLoader.php line 44
at YamlFileLoader->load('config.yml') in AppExtension.php line 21
at AppExtension->load(array(array()), object(ContainerBuilder)) in MergeExtensionConfigurationPass.php line 55
at MergeExtensionConfigurationPass->process(object(ContainerBuilder)) in MergeExtensionConfigurationPass.php line 39
at MergeExtensionConfigurationPass->process(object(ContainerBuilder)) in Compiler.php line 107
at Compiler->compile(object(ContainerBuilder)) in ContainerBuilder.php line 545
at ContainerBuilder->compile() in Kernel.php line 477
at Kernel->initializeContainer() in Kernel.php line 117
at Kernel->boot() in Kernel.php line 166
at Kernel->handle(object(Request)) in app_dev.php line 30

谢谢。

【问题讨论】:

    标签: symfony dependency-injection


    【解决方案1】:

    原来我并没有真正了解整个过程。让我们稍微澄清一下。

    目标是公开服务并让开发人员能够自定义参数/依赖项。

    如果这不是您的意思,请浏览 SO,真相就在那里
    当你希望发布你的包时,这种包配置真的很有意义。 AppBundle 不太可能被共享。我个人想提高技能。


    加载的配置文件应包含公共服务声明。它可能还设置了一些参数。
    如果要设置类似数组的属性,请声明“扁平化”参数键。 Container 的 parameterBag 不足以遍历数组树。所以$this->getParameter('my_bundle.foo_array.sub_key') 不会导致检索$parameters['mybundle']['foo_array']['sub_key'],而是$parameters['my_bundle.foo_array.sub_key']

    # AppBunble/Resources/config/config.yml
    parameters:
        # Prepending a custom namespace may help keep things clearer but is not required
        my_ns.foo_property: "@foo_service"
        my_ns.bar_property: "bar_value"
        my_ns.array_key.baz_property: "baz_value"
        my_ns.array_key.qux_property: "qux_value"
    

    您可以声明通常的方式和缩进子键(使用 yaml),但在这种情况下,它必须在您的包的扩展类中“扁平化”(见下文)。
    这些参数可以作为配置服务的默认值。

    # AppBunble/Resources/config/services.yml
    services:  
        app.my_service:
            class: AppBundle\Services\MyService
            arguments: ['%my_ns.foo_property%', {"address" : '%ns.array_key.baz_property%', "name":'%ns.array_key.qux_property%'}]
    

    此时您已经声明了参数和服务,在 MyBunble/Resources/config/* 内部的多个文件之间拆分或不拆分

    然后呢?由于您公开了服务,因此使用您的包的开发人员可能希望提供替代配置。你的工作是在你的 bundle 的 Extension(例如 AppBundle/DependencyInjection/AppExtension.php) 中实现它。一切都发生在 load 方法中。

    • 您的默认参数必须被收集并注入到容器中(使用 Symfony\Component\DependencyInjection\Loader\YamlFileLoader 或 ..XMLFileLoader 等帮助程序……)。

      $loader = new YamlFileLoader( $container, new FileLocator(__DIR__.'/../Resources/config') );
      $loader->load('config.yml');
      // ...
      $loader->load('services.yml');
      
    • 第一个参数 array $configs 包含我们捆绑包的公共选项覆盖。它的内容来自应用程序主“配置”文件。用户可以在 config.yml 和 config_dev.yml 中设置选项,然后 $configs 将公开 2 个条目。无论如何,$configs 是您必须查找开发人员可能设置的一些选项的地方。

      app:
          foo_property: 'some value'
          array_key:
            qux_property: "jd@mydomain.com"
      
    • 如果它不为空,则必须借助配置类(例如 AppBundle/DependencyInjection/Configuration.php)对其进行验证。

      $configOverride = $this->processConfiguration( new Configuration() , $configs);
      
    • 配置类。

      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()
                  // ...
                  ->end();
              return $treeBuilder;
          }
      }
      

      "app" 是 symfony 为填充 AppExtension::load $configs 参数而期望找到的根键。按照惯例,它是捆绑名称的蛇形版本,减去“捆绑”后缀。它可以自定义,但您需要设置一些方法覆盖,以获取更多信息see documention

    • 验证自定义选项后,您可以与默认值合并、转换、覆盖或其他任何方式。最后,您需要将结果选项集设置为容器参数。一旦容器尝试实例化您的服务,就会使用这些选项。

      class AppExtension extends Extension
      {
        public function load(array $configs, ContainerBuilder $container)
        {
      
          $loader = new YamlFileLoader( $container, new FileLocator(__DIR__.'/../Resources/config') );
          $loader->load('config.yml');
          // Merging datas…
          $container->setParameter('app', $resultingConfig);
          $loader->load('services.yml');
      

    注意:我使用的是 Sf 3.0.3。
    我希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-25
      • 2015-04-09
      • 2018-05-27
      • 1970-01-01
      • 1970-01-01
      • 2022-12-09
      • 2013-05-01
      • 2014-03-06
      相关资源
      最近更新 更多