Php 从自定义捆绑包中的控制器获取配置参数

Php 从自定义捆绑包中的控制器获取配置参数,php,symfony,symfony4,Php,Symfony,Symfony4,我试图从配置yaml文件中获取一些参数,我正在执行以下操作: namespace ExampleVendor\AdminBundle\Controller; /** * @Route("/", name="_home") */ public function index(ParameterBagInterface $params) { $menuIcons = $this->getParameter('admin-aside-menu'); dump($menuIco

我试图从配置yaml文件中获取一些参数,我正在执行以下操作:

namespace ExampleVendor\AdminBundle\Controller;

/**
 * @Route("/", name="_home")
 */
public function index(ParameterBagInterface $params) {
    $menuIcons = $this->getParameter('admin-aside-menu');
    dump($menuIcons);

    return $this->render('@ExampleVendorAdminBundle/index.html.twig');
}
正如您所看到的,这只是一个转储函数,用于打印admin ASSIDE菜单参数,问题是,当此代码位于App\src\controller中的控制器中时,它会工作,我的意思是在主应用程序src文件夹中,但是,当我复制此代码并将其粘贴到自定义捆绑包(如vendor/myVendor/myBundle/src/controller)中的控制器中时,在重新加载页面时会出现错误:

无法解析ExampleVendor\AdminBundle\Controller\AdminController::index的参数$params,可能是您忘记将控制器注册为服务,或者没有使用Controller.service\u参数标记它

我需要ParameterBagInterface来获取这些参数,但我不知道如何将其注入控制器

好的,这似乎说明了如何解决这个问题,但是,由于我需要注入的控制器位于供应商文件夹中的自定义包中,所以答案对我毫无帮助

Project
|
+--AdminBundle <- My custom bundle, installed via composer as symlink
|  |
|  +--Controller
|  |  |
|  |  +--AdminController.php <- Heres where I want to get my parameter
|  |
|  +--DependencyInjection
|  +--Entity
|  +--Resources
|     |
|     +--config
|        |
|        +--custom.yaml <- There are my custom params
|        +--services.yaml <- Heres where I should register my controller as service?
|
+--assets
|
+--bin
|
+--config
|
+--public
|
+--src
|
+--templates
|
+--vendor <- Heres my admin bundle as symlink
这是依赖项注入中的配置类

// AdminBundle/DependencyInjection/Configuration.php

class Configuration implements ConfigurationInterface {
    public function getConfigTreeBuilder() {
        $treeBuilder = new TreeBuilder('admin-aside-menu');

        $treeBuilder->getRootNode()
            ->children()
                ->arrayNode('items')
                    ->children()
                        ->scalarNode('icon')->end()
                        ->scalarNode('title')->end()
                ->end()
            ->end()
        ;

        return $treeBuilder;
    }
}
这是bundle扩展

// AdminBundle/DependencyInjection/ExampleVendorAdminExtension .php
class ExampleVendorAdminExtension extends Extension {

    /**
     * Loads a specific configuration.
     *
     * @throws \InvalidArgumentException When provided tag is not defined in this extension
     */
    public function load(array $configs, ContainerBuilder $container) {
        $loader = new YamlFileLoader( $container, new FileLocator(__DIR__.'/../Resources/config') );
        $loader->load('custom.yaml');
        $loader->load('services.yaml');

        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);
    }
}
我在我的services.yaml中写了这篇文章,以便根据Florian的响应将我的参数注入控制器

// AdminBundle/Resources/config/services.yaml
services:
    admin-bundle.controller.admin-controller:
        class: ExampleVendor\AdminBundle\Controller\AdminController
        arguments:
            - "%admin-aside-menu%"
它似乎在某种程度上起作用,因为当我写%admin-aside-menu%错误时,一个错误页面会显示

你是说:管理员旁边的菜单

所以我认为它实际上是在加载我的param,但在我的控制器中我无法注入它

这是控制器:

/**
 * @Route(name="admin")
 *
 * Class AdminController
 * @package ExampleVendor\AdminBundle\Controller
 */
class AdminController extends AbstractController {
    public function __construct(array $adminAsideMenu) {
        dump($adminAsideMenu);
    }
}
但是当我运行这个时,我得到了这个错误

URI/admin/的控制器不可调用。控制器示例vendor\AdminBundle\Controller\AdminController具有必需的构造函数参数,但容器中不存在。您是否忘记将控制器定义为服务

开放服务.yaml 然后输入类名并选择一个id,通过自动连线获取它

services:
    ExampleVendor\AdminBundle\Controller = '@adminbundle_thenameyouchoose'
开放服务.yaml 然后输入类名并选择一个id,通过自动连线获取它

services:
    ExampleVendor\AdminBundle\Controller = '@adminbundle_thenameyouchoose'

由于任何编码标准和实践,您都不应该在供应商包中编写代码。供应商不是一个您应该推送到git存储库中的文件夹,原因之一是静态库的大小过大,实际上不属于您的项目,而且当您尝试更新composer依赖项时,这种做法也会造成混乱。您应该保持它的整洁,并将供应商添加到.gitignore中。Symfony为覆盖服务提供了良好的支持。

由于任何编码标准和实践,您不应该在供应商软件包中编写代码。供应商不是一个您应该推送到git存储库中的文件夹,原因之一是静态库的大小过大,实际上不属于您的项目,而且当您尝试更新composer依赖项时,这种做法也会造成混乱。您应该保持它的整洁,并将供应商添加到.gitignore中。Symfony为覆盖服务提供了良好的支持。

构建自己的捆绑包并不简单

从您与我们共享的bundle结构中,我可以看到您已经拥有了Dependency injection文件夹

此文件夹应包含两个文件:

Configuration.php YourBundleNameExtension.php 要注入控制器的参数应该在包的配置中,因此必须完成configuration.php才能添加它。我不是这方面的专家,所以我让你自己搜索

此外,为了访问捆绑包代码中的配置,必须将配置作为参数注入捆绑包前缀。您可以在此处找到一个示例来了解如何执行此操作:

现在,在您的Resources/services.yaml中,您可以将控制器添加为服务:

services:
    bundle_name.controller.your_controller:
        class: Your\Controller\Namespace
        arguments:
            - '%bundle_key.your_parameter_name%'
像这样的方法应该行得通,但可能还不完全清楚。如果你有更多的问题,我会尽力回答你

不要犹豫,检查现有的捆绑包作为灵感的来源

-----------编辑以回答编辑2-----------

从我看到的情况来看,您的包配置键是admin-aside菜单?也许它应该是管理菜单,而不是符合惯例。无论如何:

是的,你快到了,但是少了一些东西。您不能直接在包的配置中定义参数。相反,当您从应用程序中使用捆绑包时,在/config/packages/admin-aside-menu.yaml中会有一个如下文件:

admin-aside-menu:
    items:
        - icon: 'Home/Chair2'
          title: 'Prueba'
        - icon: 'Home/Deer'
          title: 'Prueba Venado'
这是您当前使用的捆绑包配置,应该与您在AdminBundle/DependencyInjection/configuration.php文件中定义的格式相匹配。我帮不了你,因为这不是我经常做的事

您现在可以完全删除AdminBundle/Resources/config/custom.yaml文件,因为该配置在您的应用程序中

然后在您的扩展中,您可以获得此配置,将其注入到应用程序参数中,并为您的bundle添加前缀。如果我修改你 r代码,应该是这样的:

// AdminBundle/DependencyInjection/ExampleVendorAdminExtension .php
class ExampleVendorAdminExtension extends Extension {

    /**
     * Loads a specific configuration.
     *
     * @throws \InvalidArgumentException When provided tag is not defined in this extension
     */
    public function load(array $configs, ContainerBuilder $container) {
        $loader = new YamlFileLoader( $container, new FileLocator(__DIR__.'/../Resources/config') );
        // $loader->load('custom.yaml'); not needed anymore
        $loader->load('services.yaml');

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

        // This part inject your config in parameters
        foreach ($config as $key => $value) {
            $container->setParameter('admin-aside-menu.'.$key, $value);
        }
    }
}
现在您的配置参数已经设置好了

最后一步,将其注入控制器:

// AdminBundle/Resources/config/services.yaml
services:
    admin-bundle.controller.admin-controller:
        class: ExampleVendor\AdminBundle\Controller\AdminController
        arguments:
            - "%admin-aside-menu.items%"

这样可以吗?

构建自己的捆绑包并不简单

从您与我们共享的bundle结构中,我可以看到您已经拥有了Dependency injection文件夹

此文件夹应包含两个文件:

Configuration.php YourBundleNameExtension.php 要注入控制器的参数应该在包的配置中,因此必须完成configuration.php才能添加它。我不是这方面的专家,所以我让你自己搜索

此外,为了访问捆绑包代码中的配置,必须将配置作为参数注入捆绑包前缀。您可以在此处找到一个示例来了解如何执行此操作:

现在,在您的Resources/services.yaml中,您可以将控制器添加为服务:

services:
    bundle_name.controller.your_controller:
        class: Your\Controller\Namespace
        arguments:
            - '%bundle_key.your_parameter_name%'
像这样的方法应该行得通,但可能还不完全清楚。如果你有更多的问题,我会尽力回答你

不要犹豫,检查现有的捆绑包作为灵感的来源

-----------编辑以回答编辑2-----------

从我看到的情况来看,您的包配置键是admin-aside菜单?也许它应该是管理菜单,而不是符合惯例。无论如何:

是的,你快到了,但是少了一些东西。您不能直接在包的配置中定义参数。相反,当您从应用程序中使用捆绑包时,在/config/packages/admin-aside-menu.yaml中会有一个如下文件:

admin-aside-menu:
    items:
        - icon: 'Home/Chair2'
          title: 'Prueba'
        - icon: 'Home/Deer'
          title: 'Prueba Venado'
这是您当前使用的捆绑包配置,应该与您在AdminBundle/DependencyInjection/configuration.php文件中定义的格式相匹配。我帮不了你,因为这不是我经常做的事

您现在可以完全删除AdminBundle/Resources/config/custom.yaml文件,因为该配置在您的应用程序中

然后在您的扩展中,您可以获得此配置,将其注入到应用程序参数中,并为您的bundle添加前缀。如果我修改您的代码,应该是这样的:

// AdminBundle/DependencyInjection/ExampleVendorAdminExtension .php
class ExampleVendorAdminExtension extends Extension {

    /**
     * Loads a specific configuration.
     *
     * @throws \InvalidArgumentException When provided tag is not defined in this extension
     */
    public function load(array $configs, ContainerBuilder $container) {
        $loader = new YamlFileLoader( $container, new FileLocator(__DIR__.'/../Resources/config') );
        // $loader->load('custom.yaml'); not needed anymore
        $loader->load('services.yaml');

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

        // This part inject your config in parameters
        foreach ($config as $key => $value) {
            $container->setParameter('admin-aside-menu.'.$key, $value);
        }
    }
}
现在您的配置参数已经设置好了

最后一步,将其注入控制器:

// AdminBundle/Resources/config/services.yaml
services:
    admin-bundle.controller.admin-controller:
        class: ExampleVendor\AdminBundle\Controller\AdminController
        arguments:
            - "%admin-aside-menu.items%"


可以吗?

捆绑包中的控制器未注册为服务,因此无法使用自动连线。解决方案可以是将控制器声明为服务,并在声明中手动注入参数。此外,如果使用以前的解决方案,则可以直接注入参数,而不是注入参数包。嗨,Florian,非常感谢您的帮助。如何直接注入参数?我正在努力将我的控制器注册为一项服务,所以如果你能给我提供一个链接或一些你可以推荐的文档,我将非常感谢我编辑了我的帖子,希望它能帮你更多的忙,帮我解决这个问题。你可以分享你的服务。yaml,还有主服务。yaml?你的捆绑包中的控制器没有注册为服务,所以你不能使用自动连线。解决方案可以是将控制器声明为服务,并在声明中手动注入参数。此外,如果使用以前的解决方案,则可以直接注入参数,而不是注入参数包。嗨,Florian,非常感谢您的帮助。如何直接注入参数?我正在努力将我的控制器注册为一项服务,所以如果你能给我提供一个链接或一些你可以推荐的文档,我会非常感激。我编辑了我的帖子,希望它能帮助你多帮我一点忙。你可以分享你的服务。yaml,也是主要服务。yaml?嗨,约翰,我有点困惑,我意识到我需要将我的控制器注册为服务,所以我发现了这一点,但在回答的评论中,有人与我有相同的问题,我只是无法让它工作,因为我的控制器是供应商文件夹,所以idk我应该写哪个名称空间和实时路由,希望它能帮你更多的忙,帮我解决这个问题你能把它声明为AdminBundle\controller吗?并从service.ymal以AdminBundle\controller\adminController的身份给他打电话。请注意增量Hi John,我有点困惑,我意识到我需要将我的控制器注册为服务,所以我发现了这一点,但在回答的评论中,有人与我有相同的问题,我只是不能让它工作,因为我的控制器是供应商文件夹,所以idk我应该写哪个名称空间和实时路由inI编辑了我的帖子,希望它能帮助你更多地帮助我解决这个问题。你能将它声明为AdminBundle\controller吗?并从service.ymal以AdminBundle\controller\adminController的身份给他打电话。请注意增量是否有方法覆盖细枝错误模板,如错误页面404、403等,但来自不同的捆绑包,而不是项目本身,如刚刚安装了捆绑包i
我不能自动覆盖那些pages@H3lltronik这正是您所需要的,但它适用于symfony 2到3版本,因为自symfony 4以来,捆绑包已被弃用,他们不再对此提供支持,但找到了一些解决方法->您可能还想检查一下是否覆盖了错误页面。是否有方法覆盖细枝错误模板,如错误页面404、403等,但来自不同的捆绑包,而不是项目本身,就像安装了一个包一样,它会自动覆盖这些包pages@H3lltronik这正是您所需要的,但它适用于symfony 2到3版本,因为自symfony 4以来,捆绑包已被弃用,他们不再对此提供支持,但找到了一些解决方法->您可能还想检查一下是否覆盖了错误页面。嗨,Florian,再次感谢您抽出时间。我只有一个小问题,bundle_键是什么?如何检查?bundle_key是bundle配置的任意前缀。在我给你的捆绑链接中,他使用orbitale_cms作为前缀Xhi Florian,我快到了,我只是最后有点卡住了,我更新了我的postHi Florian,再次感谢你抽出时间。我只有一个小问题,bundle_键是什么?如何检查?bundle_key是bundle配置的任意前缀。在我给你的捆绑链接中,他使用orbitale_cms作为前缀,我快到了,我只是在结尾有点卡住了,我更新了我的帖子