在我的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表單中的這種情況?