Symfony2,字段类型实体,与多余字段的“多对多”关系,表单中关系/ ArrayCollection / multipe复选框的问题

时间:2014-08-24 23:34:24

标签: forms symfony doctrine relation

我想创建一个简单的条目管理表单。 我得到了实体Entry,EntryUser和User。 数据库中的表:entry,entry_user和user。

我认为我接近成功,但我在这里遇到了一些问题。

在我的表单中,作者可以通过复选框检查要添加到条目的用户。 Symfony / Doctrine应该为我做关系工作并在entry_user中添加行。选中一个复选框的一行。

Entry.php

/**
 * @ORM\Entity
 * @ORM\Table(name="entry")
 */
class Entry {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\OneToMany(targetEntity="EntryUser", mappedBy="entry", cascade={"all"}, orphanRemoval=true)
     */
   protected $users;

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

    /**
     * Add user
     *
     * @param User $user
     * @return $this
     *
     */
    public function addUser(User $user)
    {
        if (!$this->users->contains($user)) {
            $this->users->add($user);
        }

        return $this;
    }

    /**
     * Remove user
     *
     * @param User $user
     * @return $this
     */
    public function removeUser(User $user)
    {
        if ($this->users->contains($user)) {
            $this->users->removeElement($user);
        }

        return $this;
    }

    /**
    * @return array
    */
    public function getUsers()
    {
        return $this->users->toArray();
    }

    /**
    * Returns the true ArrayCollection of Users.
    * @return Doctrine\Common\Collections\ArrayCollection
    */
    public function getUsersCollection()
    {
        return $this->users;
    }

}

user.php的

/**
 * @ORM\Entity
 * @ORM\Table(name="user")
 */
class User implements AdvancedUserInterface, EquatableInterface, \Serializable {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    protected $name;

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

    /**
     * Set name
     *
     * @param string $name
     * @return User
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

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

    // Many other methods for user sign in, roles and so on...

}

EntryUser.php

/**
 * @ORM\Entity
 * @ORM\Table(name="entry_user")
 */
class EntryUser {

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var integer
     *
     * @ORM\Column(name="user_id", type="integer", nullable=true)
     */
    protected $user_id;

    /**
     * @var integer
     *
     * @ORM\Column(name="entry_id", type="integer", nullable=true)
     */
    protected $entry_id;

    /**
     * @var User
     *
     * @ORM\ManyToOne(targetEntity="User", cascade={"persist"})
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $user;

    /**
     * @var Entry
     *
     * @ORM\ManyToOne(targetEntity="Entry", inversedBy="users")
     * @ORM\JoinColumn(name="entry_id", referencedColumnName="id", onDelete="SET NULL")
     */
    protected $entry;


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

    /**
     * Set user_id
     *
     * @param integer $userId
     * @return EntryUser
     */
    public function setUserId($userId)
    {
        $this->user_id = $userId;

        return $this;
    }

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

    /**
     * Set entry_id
     *
     * @param integer $entryId
     * @return EntryUser
     */
    public function setEntryId($entryId)
    {
        $this->entry_id = $entryId;

        return $this;
    }

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

    /**
     * Set user
     *
     * @param User $user
     * @return EntryUser
     */
    public function setUser(User $user = null)
    {
        $this->user = $user;

        return $this;
    }

    /**
     * Get user
     *
     * @return User
     */
    public function getUser()
    {
        return $this->user;
    }

    /**
     * Set entry
     *
     * @param Entry $entry
     * @return EntryUser
     */
    public function setEntry(Entry $entry = null)
    {
        $this->entry = $entry;

        return $this;
    }

    /**
     * Get entry
     *
     * @return Entry
     */
    public function getEntry()
    {
        return $this->entry;
    }

}

我在这里使用ManyToOne关系,因为我想使用名为EntryUser.php的文件稍后添加一些自定义字段。我需要这个,因为我必须在entry_user中存储一些额外的数据。

由于:

And it's the right thing to do. Create a new entity with the new fields, and if you need it, create a custom repository to add the methods you need.

A <--- Many to many with field ---> B

would become

A --One to many--> C (with new fields) <-- One to many--B

and of course, C has ManyToOne relationships with both A and B.

请参阅:ManyToMany relationship with extra fields in symfony2 orm doctrine

中的评论

我的EntryType.php表单定义包括以下内容,用于创建模板的复选框:

$builder->add('users', 'entity', array(
    'class' => 'MyCompMyAppBundle:User',
    'multiple' => true,
    'expanded' => true,
    'property' => 'name',
    'label' => 'Freunde',
    'query_builder' => function(EntityRepository $er) {

        return $er->createQueryBuilder('u')->select('a')
            ->from('MyComp\MyAppBundle\Entity\User', 'a')
            ->where('EXISTS (
                SELECT b
                FROM MyComp\MyAppBundle\Entity\UserFriend b
                WHERE b.created_by = :my_user_id
                AND b.friend_user_id = a.id
            )')
            ->andWhere('EXISTS (
                SELECT c
                FROM MyComp\MyAppBundle\Entity\UserFriend c
                WHERE c.created_by = a.id
                AND c.friend_user_id = :my_user_id
            )')
           ->setParameter('my_user_id', $this->user->getId());

    },
    'required' => true,
));

如您所见,我在此处为表单字段(类型:实体)加载用户对象。 UserFriend是另一个实体(table:user_friend)。朋友列表保存在那里。这里所有的朋友都被装上了。它们将显示为复选框。

现在,如果我在浏览器中转到我的表单,并检查一些用户的条目,如果我提交表单,我会收到此错误:

ORMException: Found entity of type MyComp\MyAppBundle\Entity\User on association MyComp\MyAppBundle\Entity\Entry#friends, but expecting MyComp\MyAppBundle\Entity\EntryUser

所以这很令人困惑。 我怎样才能做到这一点?

如何让symfony和doctrine自动插入entry和entry_user?

重要提示:我想让作者可以稍后编辑该条目。因此,默认情况下应选中复选框,因为它保存在entry_user中。

我只是想了解这一点并且有点困惑。但我不知道如何使这项工作。

2 个答案:

答案 0 :(得分:4)

我在网上找到了一个很棒的解决方案。我现在正在寻找很多天,但是这个家伙度过了我的一天! : - )

您可以阅读它的工作原理,并从一个很棒的例子中学习here

快乐的编码!

答案 1 :(得分:0)

对于这种情况,您应该检查&#34;表单集合&#34;在Symfony:http://symfony.com/doc/current/cookbook/form/form_collections.html

使用这种技术,您将添加一个表单类型来创建单个&#34; EntryUser&#34;之后,您可以将该表单的集合添加到父表单中。在喜欢的文章中非常容易和很好地解释。