我正在使用Symfony 2开发我的第一个复杂表单,但我已经卡住了。
This image represents my situation
所以,我有一个非常简单的实体,名为TShirt,具有以下属性:
然后我有一个包含比实体更多字段的表单:
class TShirtType extends AbstractType {
public function buildForm( FormBuilderInterface $builder, array $options ) {
$builder
->add('name', 'text', array(
'required' => true,
))
->add( 'colours', 'choice', array(
'choices' => $availableColours,
'multiple' => true,
'expanded' => true,
'mapped' => false,
))
->add( 'sizes', 'choice', array(
'choices' => $availableSizes,
'multiple' => true,
'expanded' => true,
'mapped' => false,
))
->add( 'materials', 'choice', array(
'choices' => $availableMaterials,
'multiple' => true,
'expanded' => true,
'mapped' => false,
));
}
/**
* {@inheritdoc}
*/
public function setDefaultOptions( OptionsResolverInterface $resolver ) {
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\TShirt',
));
}
public function getName() {
return 'app_bundle_tshirt_form';
}
}
我已阅读Data Transformers但据我所知,他们无法帮助我解决此问题,因为它们适用于映射字段。
给出这个场景,我想添加类似于数据变换器的东西,它采用颜色,大小和材质表单字段,并构建JSON对象以将其存储在实体中。
所以我的问题是:有没有办法自定义处理表单类中的非映射字段?
任何帮助都将非常感谢!谢谢!
答案 0 :(得分:0)
也许您可以在FormType中使用EventListener,如下所示:
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$formFactory = $builder->getFormFactory();
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (\Symfony\Component\Form\FormEvent $event) use ($formFactory, $builder) {
$data = $event->getData();
$form->add(
'customFieldName',
'text',
array('some_options' => 'someOptionValue')
);
}
注意FormEvents(此处:PRE_SET_DATA)。
此外,$data = $event->getData();
允许您获取相关对象。你可以在它上面循环并解析JSON (或创建尽可能多的JSON数组包含的方法并反复调用它们),以便显示尽可能多的$form->add(..
。 JSON数组。
答案 1 :(得分:0)
将它存储在tagsData中不是一个好方法!
SYMFONY 2.7的解决方案
Controller.php这样:
$colors = [
'white' => 'white',
'black' => 'black',
'green' => 'green'
];
$sizes = [
'M' => 'M',
'L' => 'L',
'XL' => 'XL'
];
$materials = [
'Cotton' => 'Cotton',
'Wool' => 'Wool',
'Silk' => 'Silk'
];
$object = new TShirt();
$form = $this->createForm(new TShirtType(), $object, ['colours' => $colors, 'sizes' => $sizes, 'materials' => $materials]);
$form->handleRequest($request);
TShirtType.php
class TShirtType extends AbstractResourceType
{
public function buildForm( FormBuilderInterface $builder, array $options ) {
$builder
->add('name', 'text', array(
'required' => true,
))
->add( 'colours', 'choice', array(
'choices' => $options['colours'],
'multiple' => true,
'expanded' => true,
'mapped' => false
))
->add( 'sizes', 'choice', array(
'choices' => $options['sizes'],
'multiple' => true,
'expanded' => true,
'mapped' => false
))
->add( 'materials', 'choice', array(
'choices' => $options['materials'],
'multiple' => true,
'expanded' => true,
'mapped' => false
));
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event)
{
$object = $event->getData();
$form = $event->getForm();
$tagsData = [
'colours' => $form->get('colours')->getData(),
'sizes' => $form->get('sizes')->getData(),
'materials' => $form->get('materials')->getData(),
];
$object->setTagsData($tagsData);
$event->setData($object);
});
}
public function finishView(FormView $view, FormInterface $form, array $options)
{
$tagsData = $view->vars['data']->getTagsData();
if($tagsData) {
$types = ['colours', 'sizes', 'materials'];
foreach($types as $type) {
foreach($view->offsetGet($type) as $checkbox) {
$checkbox->vars['checked'] = isset($tagsData[$type]) && in_array($checkbox->vars['value'], $tagsData[$type]);
}
}
}
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver ) {
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\TShirShirt',
));
$resolver->setRequired(['colours', 'sizes', 'materials']);
}
public function getName() {
return 'app_bundle_tshirt_form';
}
}
答案 2 :(得分:0)
我终于通过创建自定义DataMapper来解决问题,正如本教程所解释的那样 https://webmozart.io/blog/2015/09/09/value-objects-in-symfony-forms/