Pregunta

Tengo una aplicación SIMFONY2 simple con dos entidades: Municipio y PDI. Hay una relación "uno a muchos" entre el municipio y los PDI (es decir: cero o más POIs colocados en un municipio), por lo que los archivos de la entidad son así:

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;
    }
}

En este punto, quiero administrar la relación de uno a muchos entre el municipio y sus PDI desde el formulario Municipio Agregar / Editar en Sonata Admin.

He seguido las instrucciones explicadas en http://sonata-project.org/bundles/doctrine-orm-admin/master/doc/reference/form_field_definition.html#advanced-usage-one-to-many , por lo que el archivo de clase MunicipalityMin es:

poc / pocbundle / admin / municipalitymin.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'
            ))
    ;
    }
}

El formulario que estoy tratando de obtener es un formulario Agregar / Editar donde puedo definir el nombre del municipio y agregar / agregar / eliminar los PDI asociados de la entidad POI, pero lo que realmente obtengo es un formulario donde puedo definir el nombre del municipio, y gestiona la entidad POI en un tipo de sub-forma.

Esta pantalla de pantalla describe el resultado -> http://i.imgur.com/nm1ywwh.png

Me refiero, de esta manera, puedo agregar nuevos PDI y relaciones con cualquier municipio (es decir, Los Ángeles), pero lo que estoy tratando de obtener es una lista de Al POI que están relacionados con este municipio y la posibilidad. a:

  • Añadir nuevas relaciones (es decir: asociar un POI huérfano como estatua de la libertad a este municipio (Nueva York)).
  • Eliminar las relaciones existentes (es decir: eliminar una relación incorrecta como "Walt Disney Concert Hall" en Nueva York)

He visto la forma de administrar esto en la forma inversa, seleccionando el Municipio relacionado con cada PDI en el Formulario de Edición / Edición de PDI (muchos a uno), pero me pregunto si hay alguna forma de administrar esto Relaciones en la otra entidad.

¿Puedo hacer esto en SONATAADMIN? ¿Alguna pista?

Actualización: resolvió la interfaz de usuario y agregando PDI, pero no eliminando

Tengo la manera de mostrar el widget que busco, definiendo el formulario de esta manera:

protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper
        ->add('name')
        ->add('pois', null, array(), array(
            'edit' => 'inline',
            'inline' => 'table',
            'sortable'  => 'position'
        ))
;
}

Lo que hice es cambiar 'sonata_type_collection' para el valor nulo. Ahora recibo un formulario como esta captura de pantalla -> correcto formulario gui

... que como solo el comportamiento que quiero.

Inicialmente, las adiciones en este widget (es decir: agregar nuevos PDI a un municipio), no persistió. Gracias al comentario de Radomir Wojtera, me di cuenta de que había métodos que no se implementaban en mi clase de entidad municipal (Setpois, Addpoi y RemoverPoi).

Añadido estos métodos ...

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);
}

... y ahora puedo tomar nuevos PROIS para un municipio, pero cuando quito algunos POIs, no se disociaron. Así que puedo agregar relaciones, pero no quitar.

¿Fue útil?

Solución

Finalmente, puedo resolver el segundo problema (eliminar PDI de un municipio no funcionó) configurando OrphanRemoval= True en la configuración de la entidad

class Municipality
{
    /**
     * @ORM\OneToMany(targetEntity="Poi", mappedBy="municipality", cascade={"persist"}, orphanRemoval=true))
     */
    protected $pois;
...

El primer problema se resuelve según lo comentó en la actualización de la pregunta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top