Symfony2 и Selectize.js: Самый простой способ сохранить новые элементы в типе полей сущностей?

В Symfony2 у меня есть BandType, где я добавляю сущность Tag:

->add('tags', 'entity', [
'label' => 'Tags',
'class' => 'DbBundle:Tag',
'property' => 'title',
'multiple'  =>  true,
])

Это генерирует множественный элемент выбора, где я могу выбрать существующие теги из базы данных (доктрина). Но я нужно динамически добавлять новые теги, которые еще не существуют.

На стороне клиента я использую плагин jQuery Selectize.js, что позволяет мне добавить новый тег в поле выбора. Но после отправки формы новый теги не сохраняются.

Итак, мой вопрос — Какой самый простой способ сохранить новые элементы из поля выбора (тип поля сущности)?

12

Решение

Использовать Преобразователь данных для вашего лица. А в методе reverseTransform, если вы не нашли только что добавленную полосу, просто создайте ее там, вместо того, чтобы выдавать исключение TransformationFailedException.

11

Другие решения

Одним из возможных решений является использование FormEvents. Вот пример кода:

namespace AppBundle\Form;

use AppBundle\Entity\Tag;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\OptionsResolver\OptionsResolver;

class PostType extends AbstractType
{
/**
* @var ObjectManager
*/
private $manager;

/**
* Constructor
*
* @param ObjectManager $manager
*/
public function __construct(ObjectManager $manager)
{
$this->manager = $manager;
}

/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('content')
->add('tags')
;
$builder->get('tags')->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) {
$choiceList = $event->getForm()->getConfig()->getAttribute('choice_list');
$array = is_null($event->getData()) ? [] : $event->getData();
$choices = $choiceList->getChoicesForValues($array);

if (count($choices) !== count($array)) {
$values = $choiceList->getValuesForChoices($choices);
$diff = array_merge(array_diff($values, $array), array_diff($array, $values));

foreach ($diff as $value) {
$new = new Tag($value);
$this->manager->persist($new);
$this->manager->flush();
$values[] = $new->getId();
}

$event->setData($values);
}
}
);
}

/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Post'
));
}
}
0

Как описано в другом ответе, вы захотите использовать Преобразователь данных для вашей сущности, и верните новую, если вы не найдете ту, о которой просил пользователь.

Есть множество способов сделать это. Это один из способов сделать это, по сравнению с приложением, которое просто использует selectize.js, но эти понятия применимы к любому пользовательскому интерфейсу, который вы можете иметь на своем интерфейсе.

class SubjectTransformer implements DataTransformerInterface
{
protected $em;

public function __construct($em)
{
$this->em = $em;
}

//public function transform($val) { ... }

public function reverseTransform($str)
{
$repo = $this->em->getRepository('AppBundle:Subject');

$subject = $repo->findOneByName($str);
if($subject)
return $subject;

//Didn't find it, so it must be new
$subject = new Subject;
$subject->setName($str);
$this->em->persist($subject);

return $subject;
}
}

В частности, это DataTransformer для entry_type из CollectionType поле:

  • принимает менеджер объекта в своем конструкторе
  • в reverseTransformиспользует EM для извлечения значения из базы данных
  • Если он не найдет, он создает новую сущность, и сохраняет это
  • эксплицитно не очистить сущность, если ваш обработчик / контроллер формы хочет выполнить дополнительную проверку новой сущности перед ее фактической фиксацией

Другие возможные варианты включают не вызов em->persist; призвание em->flush; или (вероятно, в идеале) передача службы для управления поиском / созданием, а не непосредственное использование менеджера сущностей. (Такая служба может реализовывать обнаружение почти дубликатов, фильтрацию нецензурных выражений, давать только определенным пользователям возможность создавать новые теги и т. Д.)

-1
По вопросам рекламы [email protected]