У меня есть объект Alert, который может содержать несколько объектов. Категория:
/**
* @ORM\ManyToMany(targetEntity="MDB\AnnonceBundle\Entity\Category")
* @ORM\JoinTable(name="alerts_categories",
* joinColumns={@ORM\JoinColumn(name="alert_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="cateory_id", referencedColumnName="id")}
* )
* */
private $categories;
у меня нет никаких проблем с созданием и сохранением моего объекта, но когда я хочу редактировать, у меня проблема с представлением. Я хочу показать весь существующий объект Category, прикрепленный к моему Alert, в выбранном поле:
но в настоящее время он отображает выбранное поле для каждого прикрепленного объекта:
Итак, если у вас есть 100 категорий в этом объекте Alert, у меня будет поле выбора категории 100. То, что я хочу, - это только один из них с предварительной проверкой существующей категории.
AlertType.php
class AlertType extends AbstractType {
public function __construct() {
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->remove('user')
->remove('date')
->add('itemsToFind', 'collection')
->add("categories", "collection", array("type" => new CategoryType(true, true)))
->add('lieu')
->add("regions", "collection", array("type" => new RegionType()))
->add('fullCountry', 'checkbox', array(
'label' => 'Créer une alerte pour toute la France ?',
'required' => false,
))
;
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'MDB\UserBundle\Entity\Alert'
));
}
/**
* @return string
*/
public function getName() {
return 'mdb_userbundle_alert';
}
}
CategoryType.php
<?php
class CategoryType extends AbstractType {
public function __construct($multiple, $mapped) {
$this->multiple = $multiple;
$this->mapped=$mapped;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('category', 'entity', array(
'class' => 'MDBAnnonceBundle:Category',
'required' => true,
'choice_label' => 'nom',
'multiple' => $this->multiple,
'mapped' => $this->mapped,
'label' => false,
'attr' => array('class' => 'multiple categoriesToControl'),
'query_builder' => function(CategoryRepository $cr) {
return $cr->findAllOrderedByName();
}
));
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'MDB\AnnonceBundle\Entity\Category'
));
}
public function getName() {
return 'mdb_annoncebundle_category';
}
}
Я знаю, что это обычная причина в категории alertType, представленной как коллекция. И если использовать ai:
->add('categories', new CategoryType(false, true))
у меня будет тот, кто сказал, что symfony ждет коллекцию и получит категорию.
благодаря
Я нахожу решение,
Раньше я использовал это в своем контроллере для редактирования моего предупреждения:
$form = $this->createForm(new AlertType(), $alert);
Из-за этого SF напрямую загружает постоянную коллекцию и вызывает ошибку. Теперь я использую это:
$form = $this->createForm(new AlertType($alert));
и я сохраняю поле вручную.
if ($form->handleRequest($request)->isValid()) {
$em = $this->getDoctrine()->getManager();
$alert->setItemsToFind($form->get('itemsToFind')->getData());
$alert->setLieu($form->get('lieu')->getData());
$alert->setfullCountry($form->get('fullCountry')->getData());
$em->persist($alert);
$em->flush();
return $this->redirect($this->generateUrl('my_alerts'));
}
Для типа формы я использую это сейчас:
class AlertType extends AbstractType {
public function __construct($alert = null) {
$this->alert = $alert;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->remove('user')
->remove('date')
->add('itemsToFind', 'text', array('data' => $this->alert->getItemsToFind()))
->add('categories', new CategoryType(true, true, $this->alert))
->add('lieu', 'text', array('data' => $this->alert->getLieu()))
->add('regions', new RegionType($this->alert->getRegions()))
->add('fullCountry', 'checkbox', array(
'label' => 'Créer une alerte pour toute la France ?',
'data' => $this->alert->getFullCountry()
))
;
}
И вот строитель моего типа CategoryType:
$builder
->add('category', 'entity', array(
'class' => 'MDBAnnonceBundle:Category',
'required' => true,
'choice_label' => 'nom',
'multiple' => $this->multiple,
'mapped' => $this->mapped,
'label' => false,
'attr' => array('class' => 'multiple categoriesToControl'),
'query_builder' => function(CategoryRepository $cr) {
return $cr->findAllOrderedByName();
},'data' => (!$this->alert)?(null):($this->alert->getCategories())
));
}
конечно, я должен установить set getter и setter типа Category в Alert Entity.
Кто-нибудь знает, имеет ли этот способ низкую производительность? Я просто переписываю метод, который используется SF, поэтому я не думаю.
Надеюсь, это поможет другим людям
В вашем случае, я обычно передать параметр, такие как $alertId = null
вашего AlertType
. Позже, при инициализации вашего CategoryType
я тоже передал бы эту переменную. Затем в вашем buildForm
CategoryType
в методе buildForm
я бы выполнил запрос, основанный на $alertId
.
Чтобы поместить мои слова в код:
class AlertType extends AbstractType {
private $alertId;
public function __construct($alertId = null) {
$this->alertId = $alertId;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->remove('user')
->remove('date')
->add('itemsToFind', 'collection')
->add(
"categories",
"collection",
array(
"type" => new CategoryType(
$this->alertId, true, true
)
)
)
->add('lieu')
->add("regions", "collection", array("type" => new RegionType()))
->add(
'fullCountry',
'checkbox',
array(
'label' => 'Créer une alerte pour toute la France ?',
'required' => false,
)
);
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(
array(
'data_class' => 'MDB\UserBundle\Entity\Alert'
)
);
}
/**
* @return string
*/
public function getName() {
return 'mdb_userbundle_alert';
}
}
class CategoryType extends AbstractType {
private $alertId;
public function __construct($alertId = null, $multiple, $mapped) {
$this->multiple = $multiple;
$this->mapped = $mapped;
$this->alertId = $alertId;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('category', 'entity', array(
'class' => 'MDBAnnonceBundle:Category',
'required' => true,
'choice_label' => 'nom',
'multiple' => $this->multiple,
'mapped' => $this->mapped,
'label' => false,
'attr' => array('class' => 'multiple categoriesToControl'),
'query_builder' => function(CategoryRepository $cr) {
if(!$this->alertId) {
return $cr->findAllOrderedByName();
} else {
return $cr->findAllOrderedByNameForAlertId($alertId);
}
}
));
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array('data_class' => 'MDB\AnnonceBundle\Entity\Category'));
}
public function getName() {
return 'mdb_annoncebundle_category';
}
}
Теперь в вашем CategoryRepository
просто создайте метод под названием findAllOrderedByNameForAlertId
который возвращает определенные выбранные результаты для вашего Alert
и вы должны быть сделаны.
twig
. Обычно я создаю собственный шаблон ветки для конкретного поля Symfony Doc . Я мог бы показать вам более подходящий пример кода позже.
Alert
отображались только выбранные категории (уважительно выбирайте только те, которые находятся в БД)?