学说2.2.2,级联不与多对多关联?

时间:2012-08-05 00:28:41

标签: symfony doctrine-orm symfony-forms

我在Symfony 2.0.17-DEV和PHP 5.3.14上使用Doctrine 2.2.2。我遇到了与级联选项的多对多关联的问题。示例非常简单,希望比这位出色的董事会成员能帮助我。

无论如何,Meta超类是与User的关系的所有者。仅限相关字段和构造函数:

abstract class Meta
{
    /**
     * @ORM\ManyToMany(targetEntity="User", inversedBy="meta")
     * @ORM\JoinTable(name="meta_users",
     *     joinColumns={@ORM\JoinColumn(onDelete="CASCADE")},
     *     inverseJoinColumns={@ORM\JoinColumn(onDelete="CASCADE")}
     * )
     */
    protected $users;

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

    public function addUser(User $user)
    {
        $this->users[] = $user;
        return $this;
    }

    public function getUsers()
    {
        return $this->users;
    }
}

(实现,只是空类,LabelCategory

这很简单,有效,实际上。我的意思是在元中添加或删除用户实际上会添加/删除连接表中的相应行。

问题恰恰相反:创建/编辑用户并分配元。 User以这种方式定义与meta的关联,并添加cascade =“all”选项:

class User
{
    /**
     * @ORM\ManyToMany(targetEntity="Meta", mappedBy="users", cascade={"all"})
     */
    protected $meta;

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

    public function addMeta(Meta $meta)
    {
        $this->meta[] = $meta;
        return $this;
    }

    public function getMeta()
    {
        return $this->meta;
    }
}

我对Doctrine很新,但这不起作用。在用于创建/编辑User的Symfony 2表单中,我添加了entity类型的字段,只需选择所有元数据:

$builder
    ->add('meta', 'entity', array(
        'label'         => 'Meta',
        'class'         => 'Acme\HelloBundle\Entity\Meta',
        'property'      => 'select_label',
        'multiple' => true,
        'expanded' => true,
    ))
;

在为用户分配(使用复选框)元数据时,不会对任何表进行任何更改。怎么了?我确定我错过了什么,但我找不到。

1 个答案:

答案 0 :(得分:1)

说出我所知道的。

级联选项与保持连接表关联无关。如果在实体Meta的关系meta中找到新的User实体(或删除旧实体),则应使用此实体。也就是说,在您的表单中,您添加一些输入以创建新元素或删除现有元素,例如使用collection作为Symfony 2提供的字段类型。或者就在你做的时候:

$newMeta = new Meta();

$user->addMeta($meta);

$em->persist($user); // A new entity was found in the relation meta

据我所知,你想坚持这种关系本身; Doctrine 总是寻找拥有方以保持实体。意味着从反面您想要先保留用户,而不是在检查相应的复选框时是否保留每个元素添加或删除用户。

您的字段为entity类型,表示从您的表中提取所有元数据,并且已分配给用户的元数据标记为已选中。

我记得做过类似的事情,这里有一个"伪"控制器代码:

$em->persist($user); // Perstist the inverse side

// This is what user selected
$selectedMeta = $user->getMeta();

// All meta coming from your database
$allMeta = $em->getRepository('YourBundle::Meta')->find();

// Loop on the owning side
foreach($allMeta as $meta)
{
    // Is current meta selected?
    $isSelected = $selectedMeta->contains($meta);

    // Does this meta have already the user in it?
    $hasUser = $meta->getUsers()->contains($user);

    // To be removed: not selected and with the user
    if(!$isSelected && $hasUser)
        $meta->getUsers()->removeElement($user);

    // To be added: selected and without the user
    if($isSelected && !$hasUser)
        $meta->addUser($user);

    $em->persist($meta); // Persist the owning side and the association
}

// Apply
$em->flush();

等待确认!