【问题标题】:Symfony2 custom form type key pairSymfony2 自定义表单类型密钥对
【发布时间】:2014-05-17 13:00:05
【问题描述】:

我目前正在尝试为表单类型实现密钥对值,它与 FOSRestBundle 一起使用以允许发送如下请求:

{
    "user": {
        "username": "some_user",
        "custom_fields": {
            "telephone": "07777",
            "other_custom_field": "other custom value"
        }
    }
}

为此的后端表示如下:

用户

id、用户名、自定义字段

自定义用户字段

id,字段

CustomUserFieldValue

user_id、field_id、值

我目前已经制作了如下的自定义表单:

<?php

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('username')
            ->add(
                'custom_fields',
                'user_custom_fields_type'
            )
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(
            array(
                'data_class'      => 'Acme\DemoBundle\Entity\User',
                'csrf_protection' => false,
            )
        );
    }

    public function getName()
    {
        return 'user';
    }
}

还有我的user_custom_fields_type

<?php

class CustomUserFieldType extends AbstractType
{
    private $em;

    /**
     * @param EntityManager $em
     */
    public function __construct(EntityManager $em)
    {
        $this->em = $em;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $fields = $this->em->getRepository('AcmeDemoBundle:CustomUserField')->findAll();

        foreach($fields as $field) {
            $builder->add($field->getField(), 'textarea');
        }
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(
            array(
                'invalid_message' => 'The selected custom field does not exist'
            )
        );
    }

    public function getParent()
    {
        return 'collection';
    }

    public function getName()
    {
        return 'user_custom_fields_type';
    }
}

这一直给我一个错误,即有额外的字段。哪些是我在CustomUserFieldType 中添加的。我怎样才能让它工作?

注意:这是实际代码的简化版本,我已经尝试删除所有不相关的代码。

【问题讨论】:

    标签: php symfony symfony-forms symfony-2.3 fosrestbundle


    【解决方案1】:

    您需要使用表单侦听器向表单添加动态字段:
    http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

    在您的情况下,PRE_SET_DATA 就足够了。像这样:

    $em = $this->em;
    
    $builder->addEventListener(FormEvents::PRE_SET_DATA,
    function (FormEvent $event) use ( $em )
    {
        // get the form
        $form = $event->getForm();
    
        // fetch your data here
        $fields = $em->getRepository('AcmeDemoBundle:CustomUserField')->findAll();
    
        foreach($fields as $field)
        {
            // make sure you add the new fields to $form and not $builder from this event
            $form->add($field->getField(), 'textarea');
        }
    });
    

    【讨论】:

      【解决方案2】:

      我遇到了完全相同的问题,最后通过手动解析自定义字段来解决它。如果有其他解决方案,请分享:)

      在用户类型表单中:

      $builder->addEventListener(FormEvents::POST_SET_DATA,
              function (FormEvent $event) use ( $oEm, $oUser )
              {
                  $oForm = $event->getForm();
                  $aFields = $oEm->getRepository('MyDBBundle:CustomUserField')->findAll();
      
                  /** @var CustomUserField $oField */
                  foreach($aFields as $oField)
                  {
                      $oForm->add(
                          'custom__'.$oField->getKey(),
                          $oField->getType(),
                          array(
                              'label'     => $oField->getField(),
                              'mapped'    => false,
                              'required'  => false
                          )
                      );
                      /** @var CustomUserFieldValue $oFieldValue */
                      $oFieldValue = $oEm->getRepository('MyDBBundle:CustomUserFieldValue')->findOneBy(array('user' => $oUser, 'field' => $oField));
                      if(null !== $oFieldValue) {
                          $oForm->get('custom__' . $oField->getKey())->setData($oFieldValue->getValue());
                      }
                  }
              }
          );
      

      然后,在处理提交表单请求的控制器操作中:

      // Handle custom user fields
      foreach($oForm->all() as $sKey => $oFormData)
      {
          if(strstr($sKey, 'custom__'))
          {
              $sFieldKey = str_replace('custom__', '', $sKey);
              $oField = $oEm->getRepository('MyDBBundle:CustomUserField')->findOneBy(array('key' => $sFieldKey));
              /** @var CustomUserFieldValue $oFieldValue */
              $oFieldValue = $oEm->getRepository('MyDBBundle:CustomUserFieldValue')->findOneBy(array('user' => $oEntity, 'field' => $oField));
              if($oFieldValue === null)
              {
                  $oFieldValue = new CustomUserFieldValue();
                  $oFieldValue->setUser($oEntity);
                  $oFieldValue->setField($oField);
              }
              $oFieldValue->setValue($oFormData->getData());
              $oEm->persist($oFieldValue);
          }
      }
      

      (假设 CustomUserField 实体中同时存在“field”属性和“key”;key 是您的字段和 field 的唯一、无空格标识符是人类友好且可读的字段标签。)

      这很有效,希望对您有所帮助。但是,想知道是否有人有更好的解决方案。 :)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-24
        • 1970-01-01
        • 2012-10-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多