Я пытаюсь создать поле настраиваемого типа, расширяющее EntityType в Symfony 2.
Это новое поле не имеет выбора, пока пользователь не выберет правильный параметр с помощью ajax.
Поле работает нормально до проверки формы, где класс ChoiceToValueTransformer в своем методе reverseTransform просто не может найти любое значение в choicesList.
Это строка кода, выдающая ошибку:
$choices = $this->choiceList->getChoicesForValues(array((string) $value));
$ choices всегда пуст, и сообщение TransformationFailedException: не удалось отменить значение для пути свойства "XXXX": выбор "XX" не существует или не является уникальным.
Я пробовал PRE_SUBMIT FormEvents прикреплен к родительской форме, чтобы заполнить этот выбор, но, похоже, он не работает.
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$form = $event->getForm();
$child = $form->get('myVarName');
$data = $child->getData();
$myOptions = $child->getConfig()->getOptions();
$name = $child->getName();
$obj = $event->getData();
if (empty($obj[$name]))
return;
$choices = array($obj[$name] => $obj[$name]);
if ($data instanceof \Doctrine\ORM\PersistentCollection) {
$data = $data->toArray();
}
if ($data != null) {
if (is_array($data)) {
foreach ($data as $entity) {
$choices[$entity] = $entity;
}
} else {
$choices[$data] = $data;
}
}
$myOptions['choices'] = [];
foreach ($choices as $key => $val) {
$myOptions['choices'][] = $myOptions['em']->getRepository($myOptions['target_object'])->find($val);
}
// I've tried setting the option as well with no luck.
if (count($myOptions['choices']) > 0) {
$obj[$name] = $myOptions['choices'][array_key_first($tmp)];
$event->setData($obj);
}
$form->add($name, 'entity_ajax_select', $myOptions);
});
Я пробовал PRE_SUBMIT FormEvents, также прикрепленный к моему полю, но не работает, я также оставляю закомментированный пробный код :
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($options) {
$bdData = $this->em->getRepository($options['target_object'])->find($event->getData());
if ($bdData) {
// $event->setData($bdData);
//$event->setData([$bdData->getId() => $bdData]);
$event->getForm()->getParent()->add($event->getForm()->getName(), 'entity_ajax_select', array('class' => $options['target_object'], 'choices' => $choices, 'data' => $bdData->getId(), 'label' => $options['label'], 'attr' => $options['attr'], 'route' => $options['route']));
// $event->getForm()->getParent()->add($event->getForm()->getName(), 'entity_ajax_select', array('class' => $options['target_object'], 'choice_value' => function($entity) use ($bdData) {return $bdData;}, 'choices' => [$bdData->getId() => $bdData], 'route' => $options['route']));
}
});
Я попытался добавить преобразователь данных модели и просмотреть преобразователь данных также в классе типа поля, когда я добавляю это, то t Форма действительна, но мой объект пуст:
$builder->resetViewTransformers();
$builder->addViewTransformer(new EntityAjaxSelectTransformer($this->em, $options['target_object']), true);
$builder->resetModelTransformers();
$builder->addModelTransformer(new EntityAjaxSelectTransformer($this->em, $options['target_object']), true);
Вот код преобразователя:
<?php
namespace Kimerikal\UtilBundle\Form\DataTransformer;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
class EntityAjaxSelectTransformer implements DataTransformerInterface
{
private $objectManager;
private $className;
public function __construct(ObjectManager $objectManager, $className)
{
$this->objectManager = $objectManager;
$this->className = $className;
}
public function transform($obj)
{
if (empty($obj)) {
return '';
}
return $obj->getId();
}
public function reverseTransform($id)
{
if (!$id)
return;
$obj = $this->objectManager->getRepository($this->className)->find($id);
if (null === $obj)
throw new TransformationFailedException(sprintf('An object class: ' . $this->className . ' with id "%s" does not exist!', $id));
return $obj;
}
}
Любая идея будет высоко оценена.
Спасибо.