SonataAdmin和Symfony2中的一对多关系和添加/编辑表单

时间:2014-06-03 08:50:09

标签: php symfony doctrine-orm sonata-admin

我有一个简单的Symfony2应用程序,它有两个实体:Municipality和Poi。有一种关系"一对多"市政府和Pois之间(即:在一个市镇内有零个或多个poi),因此实体文件是这样的:

Poc的\ PocBundle \实体\ 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 \实体\ 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;
    }
}

此时,我想通过Sonata Admin中的市政添加/编辑表单管理市政当局与其poi之间的一对多关系。

我已按照http://sonata-project.org/bundles/doctrine-orm-admin/master/doc/reference/form_field_definition.html#advanced-usage-one-to-many中说明的说明操作,因此MunicipalityAdmin类文件为:

Poc的/ PocBundle /管理/ 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'
            ))
    ;
    }
}

我想要获取的表单是一个添加/编辑表单,我可以在其中定义自治市的名称,并从Poi实体添加/删除关联的poi,但我实际获得的是一个表单,我可以在其中定义名称市政当局,并以一种子形式管理Poi实体。

此屏幕截图描述结果 - &gt; http://i.imgur.com/nM1ywwh.png

我的意思是,通过这种方式,我可以添加新的Pois以及与任何市政当局(即洛杉矶)的关系,但我想要得到的是与这个市政当局有关的人员名单和的可能性:

  • 添加新的关系(即:将像自由女神像的孤儿Poi关联到这个自治市(纽约))。
  • 删除现有关系(即:删除错误的关系,例如&#34;沃尔特迪斯尼音乐厅&#34;在纽约)

我已经看到了以相反的方式管理这个的方法,选择与Poi添加/编辑表单中的每个Poi相关的市政(多对一),但是我想知道是否有任何方法可以在另一个实体中管理这种关系。

我可以在SonataAdmin中执行此操作吗?任何线索?

更新:解决了用户界面并添加了poi,但没有删除

通过以这种方式定义表单,我已经找到了展示我正在寻找的小部件的方法:

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

我所做的是改变'sonata_type_collection&#39;为null值。现在我得到一个像这个截图的表格 - &gt; Correct form GUI

......就像我想要的行为一样。

最初,此小部件中的添加内容(即:向市政府添加新的poi)并没有持续存在。感谢Radomir Wojtera的评论,我意识到我的Municipality Entity类中没有实现的方法(setPois,addPoi和removePoi)。

我添加了这些方法......

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

...现在我能够为市政府抓住新的Pois,但是当我删除一些Pois时,他们确实没有解除关联。所以我可以添加关系,但不能删除。

1 个答案:

答案 0 :(得分:1)

最后,我可以通过在实体配置中设置orphanRemoval = true来解决第二个问题(从市政当局删除Poi没有工作)

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

第一个问题已在问题更新中得到解决。