Uno per molte relazioni e aggiungere / modifica modulo a Sonataadmin e Symfony2
-
21-12-2019 - |
Domanda
Ho una semplice applicazione Symfony2 con due entità: Comune e POI. C'è una relazione "uno-a-molti" tra Comune e Pois (I.e: zero o più POI collocati in un comune), quindi i file di entità sono come questo:
poc \ pocbundle \ entity \ 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;
}
}
.
poc \ pocbundle \ entity \ poi.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;
}
}
.
A questo punto, voglio gestire la relazione uno-a molti tra il Comune e il loro POI dal Comune Aggiungi / Modifica modulo in Sonata Admin.
Ho seguito le istruzioni spiegate in http://sonata-project.org/bundles/doctrine-rm-admin/master/doc/reference/form_field_definition.html#advanced-usage-one-On-To-Many , quindi il file di classe MuniciPalitalyAdmin è:
POC / POCBundle / Amministratore / ComuneAdmin.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'
))
;
}
}
.
Questo screenhoot descrive il risultato -> http://i.imgur.com/nm1ywwh.png
Voglio dire, in questo modo, posso aggiungere nuovi POI e relazioni con qualsiasi Comune (cioè: Los Angeles), ma quello che sto cercando di ottenere è un elenco di altri POI che sono legati a questo Comune e alla Positibili A:
- .
- Aggiungi nuove relazioni (I.e: Associare un POI orfano come la statua della libertà a questo Comune (New York)).
- Rimuovi le relazioni esistenti (I.e: Rimuovi una relazione errata come "Walt Disney Concert Hall" a New York)
Ho visto il modo di gestire questo nel modo inverso, selezionando il Comune relativo a ciascun POI nel modulo Aggiungi / Modifica POI (molti a-uno), ma mi chiedo se c'è un modo per gestire questo Relazioni nell'altra entità.
Posso farlo a Sonataadmin? Qualsiasi indizio?
Ho la strada per mostrare widget che sto cercando, definendo la forma in questo modo:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name')
->add('pois', null, array(), array(
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'position'
))
;
}
.
Quello che ho fatto è cambiare 'sonata_type_collection' per il valore nullo. Ora ottengo un modulo come questo screenshot ->
... quello come solo il comportamento che voglio.
Inizialmente, le aggiunte in questo widget (I.e: aggiungere nuovi POI a un Comune), non persistono. Grazie al commento di Radomir Wojtera, mi sono reso conto che c'erano metodi non implementati nella mia classe di entità municipale (Setpois, AddPoi e Removepoi).
Ho aggiunto questo metodo ...
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);
}
.
... E ora sono in grado di afferrare nuovi POI per un Comune, ma quando rimuovo alcuni POI, non hanno disassociato. Quindi posso aggiungere relazioni, ma non rimuovere.
Soluzione
Infine posso risolvere il secondo problema (la rimozione di POI da un Comune non funzionava impostando Orphanremoval= true in Configurazione Entity
class Municipality
{
/**
* @ORM\OneToMany(targetEntity="Poi", mappedBy="municipality", cascade={"persist"}, orphanRemoval=true))
*/
protected $pois;
...
.
Il primo problema è risolto come commentato nell'aggiornamento delle domande.