如何从控制器向FormType构造函数传递参数

38
在Symfony2.7中,我可以直接从控制器向表单类型构造函数传递参数来创建表单,但是在Symfony3中,我无法这样做!
$postedBy = $this->getUser()->getFullname();
$form = $this->createForm(new NewsType($postedBy));

在Symfony3之后

$form = $this->createForm(NewsType::class); // no idea how to pass parameter?

更新: 我也想从以下位置访问它:

$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
    // how to access posted_by_name here which is sent from controller
}

非常感谢任何帮助..


谢谢你的帮助,我已经自己解决了,请检查我的答案。 - Muzafar Ali
@jonathan - 那个问题的答案并没有完全回答我的问题!正如我在我的回答中更新的那样,我还需要在表单事件监听器中传递参数。 - Muzafar Ali
3个回答

69

感谢您的时间!我自己解决了这个问题:

我从NewsType构造函数中删除了参数,并使用$options数组将数据添加到postedBy表单字段中,并从控制器传递数据到$options数组,请检查以下内容:

NewsType

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('postedBy', HiddenType::class, array(
            'data' => $options['postedBy']
          )
        )
    ;
}

// WARNING: this is a MANDATORY block! Only options described here will be allowed to be passed.
public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'postedBy' => null,
    ));
}

控制器

$form = $this->createForm(NewsType::class, $news, array(
    'postedBy' => $this->getUser()->getFullname(),
);

更新: 如果您想从 addEventListener 访问 $options 数组,请使用以下代码:

```javascript const options = JSON.parse(event.target.getAttribute('data-options')); ```
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
    $postedBy = $event->getForm()->getConfig()->getOptions()['postedBy'];
}

希望对某些人有所帮助! 


或者使用:$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($options) { $postedBy = $options['postedBy']; } - Edd

14

您需要将表单定义为服务

namespace AppBundle\Form\Type;

use App\Utility\MyCustomService;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

class NewsType extends AbstractType
{
    private $myCustomService;

    private $myStringParameter;

    public function __construct(MyCustomService $service, $stringParameter)
    {
        $this->myCustomService   = $service;
        $this->myStringParameter = $stringParameter;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // Your code
    }
}

将以下内容添加到您的服务配置中:

#src/AppBundle/Resources/config/services.yml
services:
    app.form.type.task:
        class: AppBundle\Form\Type\NewsType
        arguments:
            - "@app.my_service"
            - "posted_by_name"
        tags:
            - { name: form.type }

1
这是一个好主意,但我需要一个可以从控制器+表单类型完成的解决方案。 - Muzafar Ali
对我来说,这感觉像是一个变通方法。使用“OptionsResolver”传递选项似乎是一个好的实践。或者我错了吗? - Stephan Vierkant
它很好地解决了这个问题...这正是我想要的 :) - Muzafar Ali
1
jkucharovic 给出了正确的答案。http://symfony.com/doc/current/cookbook/form/create_custom_field_type.html#creating-your-field-type-as-a-service 也说明了这一点。 - shobekhan
是的,那也是正确的解决方案,但在我的情况下,我不需要创建一个单独的服务。 - Muzafar Ali

12

你们两个都是对的。

@Muzafar 和 @jkucharovic,问题在于何时使用哪个...

正如Bernard Schussek在Symfony Forms 101中展示的那样:

1 不要将动态数据传递给构造函数...

enter image description here

2 ...而是使用自定义选项

enter image description here

3全局设置传递给构造函数(或服务)

enter image description here

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接