У меня есть следующая структура db:
User > UserRole < Role UserId UserRoleId RoleId Name UserId Name RoleId Active CreationDate
И мои классы doctrine2 определяются следующим образом:
/** * @var Roles * * @ORM\ManyToMany(targetEntity="SecRole") * @ORM\JoinTable(name="SEC_USER_ROLE", * joinColumns={@ORM\JoinColumn(name="SEC_USER_ID", referencedColumnName="SEC_USER_ID")}, * inverseJoinColumns={@ORM\JoinColumn(name="SEC_ROLE_ID", referencedColumnName="SEC_ROLE_ID")} * ) */ private $userRoles; public function __construct() { parent::__construct(); $this->userRoles = new \Doctrine\Common\Collections\ArrayCollection(); } public function addSecRole(\myEntity\SecRole $role) { $exists = $this->userRoles->exists(function($key, $elem) use($role) { return isset($elem) && $elem->getSecRoleCode() == $role->getSecRoleCode(); }); return !$exists && $this->userRoles->add($role); }
Чтобы добавить новую роль пользователю, выполните следующие действия:
$r = $rolerep->findOneBySecRoleCode('SystemAdmin'); $u = $userrep->findOneByUserLogin('sysadmin'); if (isset($r) && isset($u)) { if ($u->addSecRole($r)) { $em->flush(); } }
И все работает отлично, за исключением одного. События жизненного цикла не вызываются для объекта SecUserRole !. И мое подозрение в том, что поскольку Doctrine «добавляет» новую запись SecUserRole для себя, то она не вызывает события для нее.
Я слушаю prePersist, preUpdate, preDelete. Ни новый рекорд. Я попробовал onFlush, но, похоже, это тоже не получается.
Есть что-то, чего я не хватает, как я могу это решить? делать вставки самостоятельно? Конечно, это решение, но это оставляет мне делать сами запросы, чего я не хочу делать.
Ну, заранее спасибо KAT LIM
Пока что не нашел лучшего способа, но кажется, что Doctrine предполагает, что ваша таблица Join будет «автогенерирована», поэтому предполагает, что она не имеет и не нуждается в большем, чем два связанных ключа (UserId, RoleId).
То, что я сделал, чтобы решить это, было прекратить использование ManyToMany, но использовать отношение OneToMany к таблице SecUserRole. Таким образом, внутри метода addSecRole я вставил новый объект, а затем сбросил EM снаружи (как в примере выше).
Кажется, это лучший способ, который я мог бы сделать. Я получил эту идею из этого http://www.zendcasts.com/, где есть один бросок специально для сопоставлений ManyToMany.
Ну, надеюсь, это поможет всем