Соединительный стол с метаданными ухудшает работу получателей / установщиков - Doctrine 2 - PullRequest
0 голосов
/ 09 февраля 2012

Я пишу функцию, которая требует, чтобы записи моей таблицы присоединения содержали дополнительные метаданные ( Таблица объединения с метаданными ).Я попытался реализовать это в соответствии с этим разделом документации Доктрины .

См. Ниже примеры определений сущностей.

Задачатеперь getGroups и setGroups не дают / не устанавливают Group сущностей (& то же самое верно с точки зрения экземпляра Group), но они дают GroupUser сущностей.

Это добавляетсущественная задержка процесса управления этими отношениями, которая до сих пор была чрезвычайно гладкой - например, я не могу просто добавить, удалить или проверить наличие Group в коллекции, которую выдает getGroups.

Может ли кто-нибудь выявить какие-либо ошибки в моей реализации или порекомендовать более гибкий способ реализации этой концепции?

Заранее благодарен за любой ввод.

РЕДАКТИРОВАТЬ:

Моя основная проблема заключается в следующем: при использовании этой реализации для извлечения коллекции Users из сущности Group требуется посредничество этого метода Entity:

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

Я обеспокоен тем, что это может означать значительную производительность в будущем.Я не прав?

Кроме того, как можно повторно реализовать метод setUsers?

Субъект группы:

<?php

/**
 * @Entity
 * @Table(name="group")
 */

class Group {
    /**
     * @Column(type="integer", nullable=false)
     * @Id
     */
    protected $id = null;

    /**
     * @OneToMany(targetEntity="GroupUser", mappedBy="group")
     * @var \Doctrine\Common\Collections\Collection
     */
    protected $users;
}

Субъект пользователя:

<?php

/**
 * @Entity
 * @Table(name="user")
 */
class User {
    /**
     * @Column(type="integer", nullable=false)
     * @Id
     */
    protected $id = null;

    /**
     * @OneToMany(targetEntity="GroupUser", mappedBy="user")
     * @var \Doctrine\Common\Collections\Collection
     */
    protected $groups;
}

Присоединяющийся объект:

<?php
/**
 * @Entity
 * @Table(name="group_user") 
 */
class GroupUser {

    /**
     * @Id
     * @ManyToOne(targetEntity="User", inversedBy="groups")
     * @JoinColumn(name="userId", referencedColumnName="id")
     */
    protected $user;

    /**
     * @Id
     * @ManyToOne(targetEntity="Group", inversedBy="users")
     * @JoinColumn(name="groupId", referencedColumnName="id")
     */
    protected $group;

    /**
     * @Column(type="integer")
     */
    protected $relationship;
}

Связано -

1 Ответ

0 голосов
/ 10 февраля 2012

Я нашел только два примера (см. Вопрос) определений сущностей для этого конкретного типа отношений, однако нет примера кода для их использования.Таким образом, было довольно неясно, насколько текучими (или иными способами) можно было бы ожидать получающиеся в результате сеттеры и геттеры.Надеемся, что этот код поможет прояснить подход для любого, кто делает подобную попытку.

Идеальным решением в данных обстоятельствах (спасибо #doctrine @ freenode) было создание собственного репозитория - более гибкого и эффективного места длясоздание и управление связью.

Пример пользовательского репозитория для таблицы соединений с классом метаданных - Решение сопровождает код в исходном вопросе

<?php

use Doctrine\ORM\EntityRepository;

class GroupUserRepository extends EntityRepository {
    /**
     * @param \User $user
     * @param \Group $group
     * @param integer $type One of the integer class constants defined by GroupUser
     * @param string $role Optional string defining user's role in the group.
     * @return \GroupUser
     */
    public function addUserToGroup(User $user, Group $group, $relationship, $role = '') {
        $groupUser = $this->findOneBy(array('user' => $user->getId(), 'group' => $group->getId()));
        if(!$groupUser) {
            $groupUser = new GroupUser();
            $groupUser->setGroup($group);
            $groupUser->setUser($user);
            $groupUser->setRole($role);
            $groupUser->setRelationship($relationship);
            $this->_em->persist($groupUser);
        }
        return $groupUser;
    }

    /**
     * @param \User $user
     * @param \Group $group
     * @return null
     */
    public function removeUserFromGroup(User $user, Group $group) {
        $groupUser = $this->findOneBy(array('user' => $user->getId(), 'group' => $group->getId()));
        if($groupUser)
            $this->_em->remove($groupUser);
    }
}

Затем из класса таблицы соединений измените метаданные сущности соответственно на , указав пользовательский репозиторий.

<?php
/**
 * @Entity(repositoryClass="\Path\To\GroupUserRepository")
 */
class GroupUser {
    // ...   
}

Это приведет к тому, что пользовательский репозиторий выдаствместо используемого по умолчанию метод из класса сущностей простой.

<?php
/**
 * @Entity
 */
class Group {
    /**
     * @param \User $user
     * @param integer $relationship One of the integer class constants defined by GroupUser
     * @param string $role Optional string defining user's role in the group.
     * @return \GroupUser
     */
    public function addUser(User $user, $relationship, $role = '') {
        return $this->_em->getRepository('GroupUser')
                ->addUserToGroup($user, $this, $relationship, $role);
    }
}

И все примерно так же легко, как и раньше.

...