Un à de nombreuses relations et ajout / modification de formulaire à Sonataadmin et Symfony2
-
21-12-2019 - |
Question
J'ai une simple application Symfony2 avec deux entités: municipalité et POI. Il existe une relation "une à plusieurs" entre municipalité et pois (c'est-à-dire: zéro ou plus de POI placé dans une municipalité), de sorte que les fichiers entités sont comme ceci:
pooc \ pocbundle \ entité \ municipality.php
<?php
// Poc\PocBundle\Entity\Municipality.php
namespace Poc\PocBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Municipality
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="Poc\PocBundle\Entity\MunicipalityRepository")
*/
class Municipality
{
/**
* @ORM\OneToMany(targetEntity="Poi", mappedBy="municipality")
*/
protected $pois;
public function __construct()
{
$this->pois = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return Municipality
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Add pois
*
* @param \Poc\PocBundle\Entity\Poi $pois
* @return Municipality
*/
public function addPois(\Poc\PocBundle\Entity\Poi $pois)
{
$this->pois[] = $pois;
return $this;
}
/**
* Remove pois
*
* @param \Poc\PocBundle\Entity\Poi $pois
*/
public function removePois(\Poc\PocBundle\Entity\Poi $pois)
{
$this->pois->removeElement($pois);
}
/**
* Get pois
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getPois()
{
return $this->pois;
}
public function __toString()
{
return $this->name;
}
}
pooc \ pocbundle \ entité \ poii.php
<?php
// Poc\PocBundle\Entity\Poi.php
namespace Poc\PocBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Poi
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="Poc\PocBundle\Entity\PoiRepository")
*/
class Poi
{
/**
* @ORM\ManyToOne(targetEntity="Municipality", inversedBy="pois")
* @ORM\JoinColumn(name="municipality_id", referencedColumnName="id")
*/
protected $municipality;
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
* @return Poi
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set municipality
*
* @param \Poc\PocBundle\Entity\Municipality $municipality
* @return Poi
*/
public function setMunicipality(\Poc\PocBundle\Entity\Municipality $municipality = null)
{
$this->municipality = $municipality;
return $this;
}
/**
* Get municipality
*
* @return \Poc\PocBundle\Entity\Municipality
*/
public function getMunicipality()
{
return $this->municipality;
}
public function __toString()
{
return $this->name;
}
}
À ce stade, je souhaite gérer la relation unique entre la municipalité et leur POI de la municipalité Ajout / Modifier le formulaire de Sonata Admin.
J'ai suivi les instructions expliquées dans http://sonata-project.org/bundles/doctrine-orm-admin/master/doc/reeference/form_field_definition.html#advanced-Unage-one-a-many , le fichier de classe municipalityAdmin est donc:
poc / pocbundle / admin / municipalityAdmin.php
<?php
namespace Poc\PocBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Show\ShowMapper;
class MunicipalityAdmin extends Admin
{
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
->add('_action', 'actions', array(
'actions' => array(
'show' => array(),
'edit' => array(),
)
))
;
}
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name')
->add('pois', 'sonata_type_collection', array(), array(
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'position'
))
;
}
}
Cette capture d'écran décrit le résultat -> http://i.imgur.com/nm1ywww.png
Je veux dire, de cette manière, je peux ajouter de nouveaux POI et relations avec n'importe quelle municipalité (c'est-à-dire: Los Angeles), mais ce que j'essaie d'obtenir est une liste d'Al Pois qui sont liés à cette municipalité et à la posibilité à:
- Ajouter de nouvelles relations (c'est-à-dire: associer un POI orphelin comme la statue de la liberté à cette municipalité (New York)).
- Supprimer les relations existantes (c'est-à-dire: supprimer une relation incorrecte comme "Walt Disney Concert Hall" à New York)
J'ai vu le moyen de gérer cela à l'inverse, sélectionnez la municipalité liée à chaque POI dans le formulaire d'ajout / modification du POI (nombre-à-un), mais je me demande si y a-t-il un moyen de gérer cela relations dans l'autre entité.
Puis-je faire cela à Sonataadmin? Tout indice?
J'ai le moyen de montrer le widget que je cherche, en définissant le formulaire de cette manière:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name')
->add('pois', null, array(), array(
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'position'
))
;
}
Qu'est-ce que j'ai fait, c'est changer 'Sonata_Type_Collection' pour la valeur null. Maintenant, je reçois un formulaire comme cette capture d'écran ->
... que comme le comportement que je veux.
Initialement, les ajouts de ce widget (c'est-à-dire ajouter de nouveaux POI à une municipalité), n'a pas persisté. Grâce au commentaire de Radomir Wojtera, j'ai réalisé qu'il y avait des méthodes non implémentées dans ma catégorie d'entité municipalité (Setpois, AddPoi et RemovePoi).
J'ai ajouté cette méthode ...
public function setPois($pois)
{
if (count($pois) > 0) {
foreach ($pois as $i) {
$this->addPoi($i);
}
}
return $this;
}
public function addPoi(\Poc\PocBundle\Entity\Poi $poi)
{
$poi->setMunicipality($this);
$this->pois->add($poi);
}
public function removePoi(\Poc\PocBundle\Entity\Poi $poi)
{
$this->pois->removeElement($poi);
}
... et maintenant je suis capable de prendre de nouveaux pois pour une municipalité, mais quand je suppose de Pois, ils ne sont pas dissociés. Donc, je peux ajouter des relations, mais pas enlever.
La solution
Enfin, je peux résoudre le deuxième problème (supprimer POI d'une municipalité n'a pas fonctionné) en définissant Orphanremoval= True dans la configuration de l'entité
class Municipality
{
/**
* @ORM\OneToMany(targetEntity="Poi", mappedBy="municipality", cascade={"persist"}, orphanRemoval=true))
*/
protected $pois;
...
Le premier problème est résolu comme commenté dans la mise à jour de la question.