2015-09-26 85 views
2

在我的symfony2應用程序中,我構建了一個表單類型,可以讓我從ajax請求中填充選擇內容。當表單無效時,symfony2自定義表單類型數據爲空

我已經使用了一個數據轉換器,它將一個對象轉換爲一對id和value,並將一個id反向轉換爲一個對象。

它運作良好,除非表格無效。在這種情況下,我的自定義表單類型字段是空的,我必須重新輸入數據,然後才能重新提交表單,然後才能更正格式不正確的格式。

有人知道如何解決這個問題嗎?我錯過了什麼?

我的形式:

<?php 
//src/AppBundle/Form/Type/TimePickerType.php 

namespace AppBundle\Form\Type; 

use AppBundle\Form\DataTransformer\IdToEntityTransformer; 
use Doctrine\ORM\EntityManager; 
use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\Form\FormInterface; 
use Symfony\Component\Form\FormView; 
use Symfony\Component\OptionsResolver\OptionsResolverInterface; 
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker; 

class Select2EntitySearchType extends AbstractType 
{ 
    /** 
    * @var EntityManager 
    */ 
    private $entityManager; 
    /** 
    * @var AuthorizationChecker 
    */ 
    private $authorizationChecker; 

    public function __construct(EntityManager $entityManager, AuthorizationChecker $authorizationChecker) 
    { 
     $this->entityManager = $entityManager; 
     $this->authorizationChecker = $authorizationChecker; 
    } 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     if (class_exists($options['search_class']) == false) { 
      throw new \Exception("La classe n'a pas été reconnue : " . $options['search_class']); 
     } 

     $transformer = new IdToEntityTransformer($options, $this->entityManager, $this->authorizationChecker); 

     $builder->addModelTransformer($transformer); 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setRequired(array(
      'search_class', 
     )); 

     $resolver->setDefaults(array(
      'search_parameter' => '', 
      'multiple' => false, 
      'is_granted' => null, 
      'compound' => false 
     )); 
    } 

    public function buildView(FormView $view, FormInterface $form, array $options) 
    { 
     $view->vars = array_replace($view->vars, array(
      'search_class' => $options['search_class'], 
      'search_parameter' => $options['search_parameter'], 
     )); 
    } 

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

我datatransformer:

<?php 

namespace AppBundle\Form\DataTransformer; 

use Doctrine\Entity; 
use Doctrine\ORM\EntityManager; 
use Symfony\Component\Form\Exception\TransformationFailedException; 
use Symfony\Component\Form\DataTransformerInterface; 
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker; 

/** 
* @author Bernhard Schussek <[email protected]> 
*/ 
class IdToEntityTransformer implements DataTransformerInterface 
{ 
    /** 
    * @var array 
    */ 
    private $options; 

    /** 
    * @var EntityManager 
    */ 
    private $entityManager; 
    /** 
    * @var AuthorizationChecker 
    */ 
    private $authorizationChecker; 

    /** 
    * Constructor. 
    * 
    * @param $options 
    * @param EntityManager $entityManager 
    * @param AuthorizationChecker $authorizationChecker 
    * @throws \Exception 
    */ 
    public function __construct($options, EntityManager $entityManager, AuthorizationChecker $authorizationChecker) 
    { 
     if (!$options) throw new \Exception("A class argument should be given to the IdToEntityTransformer constructor"); 

     $this->options = $options; 
     $this->entityManager = $entityManager; 
     $this->authorizationChecker = $authorizationChecker; 
    } 

    /** 
    * Should be empty at first 
    * 
    * @param Entity $data 
    * @return array|mixed 
    */ 
    public function transform($data) 
    { 
     if (empty($data)) { 
      return array(); 
     } elseif (!is_array($data)) { 
      $data = array($data); 
     } 

     return array_map(function($entity){ 
      return array(
       'value' => $entity->getId(), 
       'text' => $entity->__toString() 
      ); 
     }, $data); 
    } 

    /** 
    * @param mixed $values 
    * @return array 
    */ 
    public function reverseTransform($values) 
    { 
     if (is_array($values) == false) { 
      $values = array($values); 
     } 

     if (empty($values)) { 
      return null; 
     } 

     $repo = $this->entityManager->getRepository($this->options['search_class']); 

     $entities = array_map(function($id) use ($repo) { 
      return $repo->findOneBy(array('id' => $id)); 
     }, $values); 

     if ($isGranted = $this->options['is_granted']) { 
      $entities = array_filter($entities, function($entity) use ($isGranted){ 
       return $this->authorizationChecker->isGranted($isGranted, $entity); 
      }); 
     } 

     if (empty($entities)) { 
      return $this->options['multiple'] ? array() : null; 
     } else { 
      return $this->options['multiple'] ? $entities : array_values($entities)[0]; 
     } 
    } 
} 

我的窗體類型佈局:

{% block select2_entity_search_widget %} 

    {% set attr = attr|merge({'class': attr.class ~ ' input-sm form-control select2_search'}) %} 

    <select id="{{ id }}" data-search_class="{{ search_class }}" data-search_parameter="{{ search_parameter }}" data-url="{{ path('entity_search') }}" {{ block('widget_attributes') }}> 
     {% for element in form.vars.data %} 
      <option value="{{ element.value }}" selected="selected">{{ element.text }}</option> 
     {% else %} 
      <option></option> 
     {% endfor %} 
    </select> 

{% endblock %} 

編輯:

所以當形式是無效的,如果我傾倒t他的數據,我只獲得選擇的Id。 我本來會希望在表單數據上調用reversetransform方法,如果無效,則會在此表單數據上再次調用transform方法。 處理這個問題的好方法是什麼?

如果我沒有對象,我應該在transform方法中查詢我的數據庫嗎?還是有什麼意思來處理symfony表單中的這種情況?

回答

相關問題