我在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;
}
}
(实现,只是空类,Label
和Category
)
这很简单,有效,实际上。我的意思是在元中添加或删除用户实际上会添加/删除连接表中的相应行。
问题恰恰相反:创建/编辑用户并分配元。 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,
))
;
在为用户分配(使用复选框)元数据时,不会对任何表进行任何更改。怎么了?我确定我错过了什么,但我找不到。
答案 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();
等待确认!