【问题标题】:Symfony2: how to get config parameters in Form classesSymfony2:如何在表单类中获取配置参数
【发布时间】:2012-04-18 06:45:38
【问题描述】:

如果我在控制器内,我可以使用以下方法轻松读取配置参数:

$this->container->getParameter('profession');

但是当我在其他类中时,比如 Form 类型,我如何获取配置参数?

$container = new Container(); 
$container->getParameter('profession');

上面的代码不应该也不行。

【问题讨论】:

    标签: symfony symfony-forms


    【解决方案1】:

    另一个类似的解决方案是让您的表单类型成为服务并注入所需的参数。然后你的控制器需要做的就是获取服务。用百分号将参数名称括起来。

    在 services.xml 中

        <service
            id     = "zayso_area.account.create.formtype"
            class  = "Zayso\AreaBundle\Component\FormType\Account\AccountCreateFormType"
            public = "true">
            <argument type="service" id="doctrine.orm.accounts_entity_manager" />
            <argument type="string">%zayso_core.user.new%</argument>
        </service>
    

    如果你真的想要,那么你可以注入完整的容器,尽管不鼓励这样做。

    【讨论】:

      【解决方案2】:

      现在您可以使用 ContainerAwareInterface:

      class ContactType extends AbstractType implements ContainerAwareInterface
      {
              use ContainerAwareTrait;
      
              public function buildForm(FormBuilderInterface $builder, array $options)
              {
                  $builder->add('choice_field', ChoiceType::class, [
                                  'choices' => $this->container->get('yourservice')->getChoices()
                                ]);
              }
      }
      

      在 services.yml 中:

      app.contact_type:
          class: AppBundle\Form\ContactType
          calls:
            - [setContainer, ['@service_container']]
          tags:
              - { name: form.type, alias: 'container_aware' }
      

      【讨论】:

      • 传递容器是个坏习惯。您应该只传递必需的参数。
      【解决方案3】:

      一个简单的解决方案是给你的类型一个新的变量来存储你的配置参数的值。您可以将其公开(不推荐)、添加构造函数参数或使用 setter:

      class MyType extends AbstractType{
      
          private $profession;
      
          public function __construct($profession){
              $this->profession = $profession;
          }
      
          // ...
      
      }
      

      您可以像这样在控制器中使用它:

      $myType = new MyType($this->container->getParameter('profession'));
      // use mytype with form
      

      毕竟,表单根本不应该知道容器,因为您会将它们捆绑在一起,从而难以测试或更换容器。这与容器的整体理念背道而驰。

      另一方面,使用构造函数/设置器来注入参数相当不错,因为您在测试时不需要知道它们的来源,可以随时更改它们的来源,并且如上所述,不要对容器有依赖关系。

      【讨论】:

      • 谢谢,这会奏效。但是我已经将它实现为服务并注入了参数。我认为这是一种更好的方法。
      【解决方案4】:

      在 Symfony 4 中,您应该首先将表单定义为服务,然后在 config/services.yaml 中将正确的参数传递给它

      parameters:
          locale: 'en'
          upload_dir: '%kernel.project_dir%/public/uploads/avatars'
      
      services:
          App\Form\FilemanagerType:
              arguments: ['%upload_dir%']
              tags: [form.type]
      

      在你的表单类中获取参数(这里是上传目录)像这样

      class FilemanagerType extends AbstractType
      {
          private $upload_dir;
          function __construct(string $upload_dir)
          {
              $this->upload_dir= $upload_dir;
          }
      }
      

      希望对你有帮助

      【讨论】:

        【解决方案5】:

        在 Symfony 4.1 中,您只需将 ParameterBagInterface 添加到 Form 构造函数中:

        public function __construct(ParameterBagInterface $parameterBag)
        {
            $this->parameterBag = $parameterBag;
        }
        

        然后获取你的参数:

        $profession = $this->parameterBag->get('profession');
        

        【讨论】:

          【解决方案6】:

          您也可以使用 Setter 注入。来自http://symfony.com/doc/current/book/service_container.html#optional-dependencies-setter-injection

          如果你有一个类的可选依赖项,那么“setter injection”可能是一个更好的选择。这意味着使用方法调用而不是通过构造函数注入依赖项。该类将如下所示:

          namespace AppBundle\Newsletter;
          
          use AppBundle\Mailer;
          
          class NewsletterManager
          {
              protected $mailer;
          
              public function setMailer(Mailer $mailer)
              {
                  $this->mailer = $mailer;
              }
          
              // ...
          }
          

          通过setter方法注入依赖只需要改变语法:

          # app/config/services.yml
          services:
              app.mailer:
                  # ...
          
              app.newsletter_manager:
                  class:     AppBundle\Newsletter\NewsletterManager
                  calls:
                      - [setMailer, ['@app.mailer']]
          

          【讨论】:

          • setter 何时被调用?
          • 它由 Symfony 服务容器自动调用
          • 这解释了我的问题是谁调用它是在对象生命周期的哪个时间点调用它。当我使用该服务时,我是否可以保证 $mailer 不会为空?
          【解决方案7】:

          在 Symfony3 中,可以这样做 -

          在控制器处

          $form = $this->createForm(FormType::class, $abc, array('firstargument' => $firstargumentvalue, 'second' => $secondvalue));
          

          在表单类型

          public function configureOptions(OptionsResolver $resolver)
              {
                  $resolver->setDefaults(array('data_class' => abc::class, 'firstargument' => null, 'second' => null));
              }
          
          public function buildForm(FormBuilderInterface $builder, array $options)
              {
          
                  $first = $options['firstargument'];
                  $second = $options['second'];
          }
          

          您可以在表格中使用上述值

          【讨论】:

            【解决方案8】:

            在 Symfony 4.1 中

            services:
                # ...
                _defaults:
                    bind:
                        $projectDir: '%kernel.project_dir%'
            
            use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
            
            class MessageGenerator
            {
                private $params;
            
                public function __construct(ParameterBagInterface $params)
                {
                    $this->params = $params;
                }
            
                public function someMethod()
                {
                    $parameterValue = $this->params->get('parameter_name');
                    // ...
                }
            }
            

            请参考https://symfony.com/blog/new-in-symfony-4-1-getting-container-parameters-as-a-service

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-10-10
              • 1970-01-01
              • 2013-04-30
              • 1970-01-01
              • 2012-05-10
              • 2015-09-18
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多