将集合实体表示为一个多字段
represent collection entity as one multiple field
我有一个可以包含多个实体类别的实体警报:
/**
* @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;
我对我的实体的创建和持久化没有任何问题,但是当我想编辑时,我遇到了表示问题。我想在像这样的 selected 字段中显示附加到我的警报的所有当前类别实体:
但目前它显示每个附加实体的 selected 字段:
因此,如果在此警报实体中有 100 个类别,我将有 100 个类别 select 字段。我想要的只是预先检查了现有类别的一个。
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 类别表示为一个集合。如果我使用:
->add('categories', new CategoryType(false, true))
我会有一个人说 symfony 正在等待收集并获得一个类别。
谢谢
在您的情况下,我通常会将 $alertId = null
等参数传递给您的 AlertType
。稍后,在初始化您的 CategoryType
时,我也会传递该变量。然后在 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
的方法,其中 returns 为您的 Alert
选择的特定结果,您应该完成了。
我找到了解决办法,
以前我在我的控制器中使用它来编辑我的警报:
$form = $this->createForm(new AlertType(), $alert);
因为那个SF直接加载了persistent collection导致了错误。现在我用这个:
$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())
));
}
当然我必须在警报实体中设置类别类型的集合getter和setter。
有人知道这种方式是否性能低下?我只是重写了SF习惯使用的方法,所以我不认为。
希望这对其他人有帮助
我有一个可以包含多个实体类别的实体警报:
/**
* @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;
我对我的实体的创建和持久化没有任何问题,但是当我想编辑时,我遇到了表示问题。我想在像这样的 selected 字段中显示附加到我的警报的所有当前类别实体:
但目前它显示每个附加实体的 selected 字段:
因此,如果在此警报实体中有 100 个类别,我将有 100 个类别 select 字段。我想要的只是预先检查了现有类别的一个。
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 类别表示为一个集合。如果我使用:
->add('categories', new CategoryType(false, true))
我会有一个人说 symfony 正在等待收集并获得一个类别。
谢谢
在您的情况下,我通常会将 $alertId = null
等参数传递给您的 AlertType
。稍后,在初始化您的 CategoryType
时,我也会传递该变量。然后在 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
的方法,其中 returns 为您的 Alert
选择的特定结果,您应该完成了。
我找到了解决办法,
以前我在我的控制器中使用它来编辑我的警报:
$form = $this->createForm(new AlertType(), $alert);
因为那个SF直接加载了persistent collection导致了错误。现在我用这个:
$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())
));
}
当然我必须在警报实体中设置类别类型的集合getter和setter。
有人知道这种方式是否性能低下?我只是重写了SF习惯使用的方法,所以我不认为。
希望这对其他人有帮助