简体   繁体   中英

SonataAdminBundle, sonata_type_collection and embed forms

Mensaje StackOverflow

Hello everybody!

I'm having a strange issue (cause it was already solved many months ago) regarding SonataAdminBundle. The thing is that my embed forms is not longer working. My approach basically follows this tutorial: http://simonsaysblog.net/sonataadminbundle-doctrine-and-onetomany-relationship (and many other tutorials around the Net).

I have the "User" entity (the one installed by Sonata User Bundle over FOSUserBundle) which has two entities: Email and Phone, in a Many-to-One relationship with User (One user has many email addresses and many phone numbers).

Call the User form display this error message:

The current field `emails` is not linked to an admin. Please create one for the target entity : ``

(The entity name is blank as you can notice).

User.php

<?php

namespace Application\Sonata\UserBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Mapping as ORM;
use Sonata\UserBundle\Entity\BaseUser as BaseUser;

/**
*
* @ORM\Table(name="system_user")
* @ORM\Entity(repositoryClass="Application\Sonata\UserBundle\Repository\UserRepository")
* @ORM\HasLifecycleCallbacks
*/
class User extends BaseUser
{
    /**
    * @var integer $id
    *
    * @ORM\Column(name="id", type="integer", nullable=false)
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="SEQUENCE")
    * @ORM\SequenceGenerator(sequenceName="system_user_id_seq", allocationSize=1, initialValue=1)
    */
    protected $id;

    /**
    * @var ArrayCollection emails
    *
    * @ORM\OneToMany(targetEntity="MyApp\MyBundle\Entity\Email", mappedBy="user", cascade={"persist", "remove"}, orphanRemoval=true)
    */
    protected $emails;

    /**
    * @var ArrayCollection phones
    *
    * @ORM\OneToMany(targetEntity="MyApp\MyBundle\Entity\Phone", mappedBy="user", cascade={"persist", "remove"}, orphanRemoval=true)
    */
    protected $phones;

    // some other attributes

    /**
    * Constructor
    */
    public function __construct()
    {
        parent::__construct();

        $this->emails       = new \Doctrine\Common\Collections\ArrayCollection();
        $this->phones       = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
    * Get id
    *
    * @return integer $id
    */
    public function getId()
    {
        return $this->id;
    }

    /**
    * Set emails
    *
    * @param $emails
    */
    public function setEmails($emails)
    {
        $this->emails = new ArrayCollection();

        foreach ($emails as $email) {
            $this->addEmails($email);
        }
    }

    /**
    * Get emails
    *
    * @return ArrayCollection
    */
    public function getEmails()
    {
        return $this->emails;
    }

    /**
    * Add email
    *
    * @param \MyApp\MyBundle\Entity\Email $email
    */
    public function addEmails(\MyApp\MyBundle\Entity\Email $email)
    {
        $email->setUser($this);

        //$this->emails[] = $email;
        $this->emails->add($email);
    }

    /**
    * Remove email address
    *
    * @param \MyApp\MyBundle\Entity\Email $email
    */
    public function removeEmails(\MyApp\MyBundle\Entity\Email $email)
    {
        $this->emails->removeElement($email);
    }

    // some other methods
}

UserAdmin.php

<?php

namespace Application\Sonata\UserBundle\Admin;

use FOS\UserBundle\Model\UserManagerInterface;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Sonata\UserBundle\Model\UserInterface;

class UserAdmin extends Admin
{
    // some other methods

    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            ->with('General')
                ->add('username')
                ->add('email')
                ->add('plainPassword', 'text', array(
                    'required' => (!$this->getSubject() || is_null($this->getSubject()->getId()))
                ))
                ->add('emails', 'sonata_type_collection',
                    array(
                        'label' => 'Emails',
                        'by_reference' => false,
                        'cascade_validation' => true
                    ),
                    array(
                        'edit' => 'inline',
                        'inline' => 'table',
                        'allow_delete' => true
                    )
                )
            // many other fields
        ;
    }

    // some other methods
}

Email.php

<?php

namespace MyApp\MyBundle\Entity;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Mapping as ORM;

/**
* Email
*
* @ORM\Table(name="email")
* @ORM\Entity(repositoryClass="MyApp\MyBundle\Repository\EmailRepository")
* @ORM\HasLifecycleCallbacks
*/
class Email
{
    /**
    * @var integer
    *
    * @ORM\Column(name="id", type="integer", length=18, nullable=false)
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="SEQUENCE")
    * @ORM\SequenceGenerator(sequenceName="email_id_seq", allocationSize=1, initialValue=1)
    */
    private $id;

    /**
    * @var \Application\Sonata\UserBundle\Entity\User
    *
    * @ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", inversedBy="emails")
    * @ORM\JoinColumns({
    *   @ORM\JoinColumn(name="system_user_id", referencedColumnName="id")
    * })
    */
    private $user;

    // some other attributes

    /**
    * Set user
    *
    * @param \Application\Sonata\UserBundle\Entity\User $user
    * @return Email
    */
    public function setUser(\Application\Sonata\UserBundle\Entity\User $user = null)
    {
        $this->user = $user;

        return $this;
    }

    /**
    * Get user
    *
    * @return \Application\Sonata\UserBundle\Entity\User
    */
    public function getUser()
    {
        return $this->user;
    }

    // some other methods
}

EmailAdmin.php

namespace MyApp\MyBundle\Admin;

use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Sonata\AdminBundle\Validator\ErrorElement;

class EmailAdmin extends Admin
{
    // other methods

    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            ->add('address')
            ->add('notes', 'textarea', array('required' => false))
        ;
    }
    // more methods
}

Phone.php

<?php

namespace MyApp\MyBundle\Entity;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Mapping as ORM;

/**
 * Phone
 *
 * @ORM\Table(name="phone")
 * @ORM\Entity(repositoryClass="MyApp\MyBundle\Repository\PhoneRepository")
 * @ORM\HasLifecycleCallbacks
 */
class Phone
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", length=18, nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="SEQUENCE")
     * @ORM\SequenceGenerator(sequenceName="phone_id_seq", allocationSize=1, initialValue=1)
     */
    private $id;
        /**
     * @var \Application\Sonata\UserBundle\Entity\User
     *
     * @ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", inversedBy="phones")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="system_user_id", referencedColumnName="id")
     * })
     */
    private $user;
   /**
     * Get id
     *
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set phoneNumber
     *
     * @param string $phoneNumber
     * @return Phone
     */
    public function setPhoneNumber($phoneNumber)
    {
        $this->phoneNumber = $phoneNumber;

        return $this;
    }

    /**
     * Get phoneNumber
     *
     * @return string
     */
    public function getPhoneNumber()
    {
        return $this->phoneNumber;
    }

    // more methods
}

PhoneAdmin.php

<?php

namespace MyApp\MyBundle\Admin;

use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Sonata\AdminBundle\Validator\ErrorElement;

class PhoneAdmin extends Admin
{
    // other methods

    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            ->add('phoneNumber')
            ->add('notes', 'textarea', array('required' => false))
        ;
    }

    // other methods
}

admin.xml

    <service id="myapp.my_bundle.admin.email" class="MyApp\MyBundle\Admin\EmailAdmin">
        <tag name="sonata.admin" manager_type="orm" group="Configuration" label="Emails" />
        <tag name="security.secure_service" />
        <argument />
        <argument>MyApp\MyBundle\Entity\Email</argument>
        <argument>MyAppMyBundle:EmailAdmin</argument>
    </service>

    <service id="myapp.my_bundle.admin.phone" class="MyApp\MyBundle\Admin\PhoneAdmin">
        <tag name="sonata.admin" manager_type="orm" group="Configuration" label="Phones" />
        <tag name="security.secure_service" />
        <argument />
        <argument>MyApp\MyBundle\Entity\Phone</argument>
        <argument>MyAppMyBundle:PhoneAdmin</argument>
    </service>

The only one thing I could think it has changed is the location of all the Sonata User files. Before they were locatated into MyApp\\MyBundle , now they are now into Application\\Sonata\\UserAdmin\\ folder (as is showed in the Sonata Project documentation).

If I take off the add() method, in the UserAdmin class, corresponding to email, the form renders OK (very slowly, but it renders OK).

如果我对消息很了解,则必须为MyApp\\MyBundle\\Entity\\EmailMyApp\\MyBundle\\Entity\\Phone实体定义另外两个管理类(以便在UserAdminsonata_type_collection它们链接为sonata_type_collection )。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM