3

我在 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 很陌生,但这不起作用。在我用于创建/编辑的 Symfony 2 表单中User,我添加了一个 type 字段entity,只需选择所有元数据:

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

将元分配(使用复选框)给用户时,任何表都没有变化。怎么了?我确定我错过了一些东西,但我找不到什么。

4

1 回答 1

1

说出我所知道的。

Cascade 选项与保持连接表关联无关。Meta当在实体的关系中找到新meta实体User(或删除旧实体)时,应该使用它。那就是,在您的表单中,您添加一些输入以创建新元或删除现有元,例如使用collectionSymfony 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();

也在等确认!

于 2012-08-05T05:24:13.320 回答