-->

Symfony2 1:M / 1:1 Relationship and Sonata Admin F

2019-01-23 10:05发布

问题:

I've hitting my head against the wall for countless hours now and I hope SO can be of help!

I have Retailer, Branch and RetailerBranches entities which work just fine, retailers can have many branches and a branch can only have one retailer. The hard part happens when trying to make Sonata Admin (SonataAdminBundle) play nice with that relationship. In their simplest form, they look like this:

Retailer entity

    /**
     * @ORM\Column(name="ID", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * Relation
     * 
     * @ORM\OneToMany(targetEntity="RetailerBranches", mappedBy="Retailer", cascade={"persist"})
     */
    protected $branches;

    public function __construct() {
        $this->branches = new ArrayCollection();
    }

RetailerBranches join table

    /**
     * @ORM\Column(name="ID", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @ORM\JoinColumn(name="Retailer_ID", referencedColumnName="ID", nullable=false)
     * @ORM\ManyToOne(targetEntity="Retailer", inversedBy="branches")
     */
    private $retailer;

    /**
     * @ORM\JoinColumn(name="Branch_ID", referencedColumnName="ID", nullable=false, unique=true)
     * @ORM\OneToOne(targetEntity="Branch", inversedBy="retailer")
     */
    private $branch;

Branch entity

    /**
     * @ORM\Column(name="ID", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * Relation
     * 
     * @ORM\OneToOne(targetEntity="RetailerBranches", mappedBy="branch", cascade={"persist"})
     */
    private $retailer;

The harder part happens when trying generate the form to allow that relationship to take shape:

RetailerAdmin

protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            ->with('Branches')
                ->add('branches', 'sonata_type_collection', array(
                    'required' => false,
                    'by_reference' => false
                ), array(
                    'edit' => 'inline',
                    'inline' => 'table',
                ))
                ->end()
        ;
    }

RetailerBranchesAdmin

protected function configureFormFields(FormMapper $formMapper)
    {
        if ($this->hasRequest()) {
            $link_parameters = array('context' => $this->getRequest()->get('context'));
        } else {
            $link_parameters = array();
        }

        $formMapper
            ->add('succursale', 'sonata_type_model_list', array(
                'class' => 'VeloRetailerBundle:Branch',
                'required' => false,
            ), array(
                'edit' => 'inline',
                'inline' => 'table',
            ))
        ;
    }

The problem:

All this sort of works, here's a screenshot:

There's a Retailer and its Branches. Yay.

Problem 1: The "Add new" button at the bottom attempts to add a RetailerBranches object instead of a simple Branch object which obviously doesn't work.

Problem 2: This method also doesn't allow the user to modify a Branch inline.

I feel like I'm close to the solution, but I just cannot quite get there. Any help would be greatly appreciated!

回答1:

For those running into the same problem, I posted the solution on GitHub

.



回答2:

When needing to edit OneToOne or other relationships on the same page in Sonata Admin you could also create Admin classes for each Entity (and add to config.yml) and simply add the entire entity to your form in you main Admin class like so:

protected function configureFormFields(FormMapper $formMapper)
    $formMapper
    ->add('yourLinkedProperty', 'sonata_type_admin')
    //other form fields
    ->end()

see Sonata Doc http://sonata-project.org/bundles/admin/master/doc/reference/form_types.html