Symfony 4 Doctrine объединяет несколько таблиц в одном свойстве - PullRequest
0 голосов
/ 11 мая 2018

Очень плохо знакомы с Symfony и Doctrine. В моей базе данных есть следующие таблицы.

mo_user

id   |    email      |   password
__________________________________
9144 | summer@h.com  |   !password! 

mo_user_role

user_id| role_id
_________________
9144   | 5

mo_permission

id | namespace            | name | description
______________________________________________
1  | admin                | -    |   -
2  | users                | -    |   -
3  | view_summary_report  | -    |   -
4  | view_user_statement  | -    |   -

mo_role_permission

role_id  | permission_id
________________________
    5    | 3
    5    | 4    

Я пытаюсь вернуть массив разрешений текущего пользователя в этом случае пользователя с id = 9144, который должен быть array('view_summary_report','view_user_statement').

Я сопоставил все таблицы с соответствующими им классами сущностей. и в MoUser.php классе сущности, который соответствует таблице mo_user, у меня есть метод разрешений, который должен возвращать массив, но мое соединение из аннотаций не выполняется,

Мой getPermissions() метод в MoUser.php

/**
 * @var Collection|MoPermission[]
 * @ORM\ManyToMany(targetEntity="App\Entity\MoPermission")
 * @ORM\JoinTable(
 *     name="mo_user_role",
 *     joinColumns={@ORM\JoinColumn(name="user_id",referencedColumnName="id")},
 *     inverseJoinColumns={@ORM\JoinColumn(name="role_id",referencedColumnName="id")}
 * )
 */
private $permissions;

 public function getPermissions()
{
    $currentPermissions = array();
    foreach ($this->permissions->toArray() as $index => $permission) {
        $currentPermissions[] = $permission->getNamespace();
    }

    //Return default role if Roles are not assigned to this user.
    if(count($currentPermissions)>0) {
        return $currentPermissions;
    } else {
        return array('DEFAULT_PERMISSION');
    }
}

Итак, я понял, что для получения того, что я хотел, нужно использовать raw sql, но я хотел бы знать аннотированный способ Symfony / Doctrine для достижения следующего необработанного SQL.

 SELECT t0.id AS id_1, t0.namespace AS namespace_2, t0.name AS name_3, t0.description AS description_4 

 FROM mo_permission t0 

 LEFT JOIN mo_role_permission ON t0.id = mo_role_permission.permission_id 

 LEFT JOIN mo_user_role ON  mo_role_permission.role_id = mo_user_role.role_id

 WHERE mo_user_role.user_id = 9144;

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

Я почти уверен, что вы могли бы выполнить этот запрос, используя Doctrine (и QueryBuilder), например ...

use Doctrine\ORM\EntityRepository

class PermissionRepository extends EntityRepository
{
    //....

    /**
     * @param UserInterface $user
     * @return array|Permission[]
     */
    public function getPermissionsForUser(UserInterface $user)
    {
        $queryBuilder = $this->createQueryBuilder('permission');

        /**
         * permissions will be in a multi-dimensional array
         * with a single key per array of 'namespace'
         */
        $permissions = $queryBuilder
            ->select('permission.namespace')
            ->join('permission.role', 'role')
            ->join('role.user', 'user')
            ->where($queryBuilder->expr()->eq('user', ':user'))
            ->setParameter('user', $user)
            ->getQuery()
            ->getArrayResult();

        if (count($permissions) > 0) {
            /**
             * If there are any permissions found just return
             * the 'namespace' property from each "sub-array"
             */
            return array_column($permissions, 'namespace');
        }

        return ['DEFAULT_PERMISSION'];
    }

    //...
}

И тогда вы бы назвали его как ..

$permissions = $repository->getPermissionsForUser($user);
0 голосов
/ 11 мая 2018

Я не думаю, что есть правильный способ достичь того, что вы пытаетесь сделать напрямую, с помощью аннотаций свойств с вашей текущей настройкой.

Вы можете достичь желаемого с помощью одного из следующих решений:

  • Один из mo_user_role и mo_role_permission не нужен, так как ни у одного из них нет дополнительного поля. У вас должна быть таблица mo_user_permission, сгенерированная отношением ManyToMany между MoUser и MoPermission, которое предоставит вам прямой доступ к MoPermission из MoUser getPermissions()

  • Другим способом было бы создание службы, которая имела бы метод GetPermissionsFromUser(MoUser $moUser) (например), вызывая правильный запрос из хранилища сущности, который вы вызывали бы при необходимости.

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

например. для последней точки:

public function getPermissions() {
    $permissions = [];
    foreach($this->roles as $role) {
        foreach($role->getPermissions() as $permission) {
            permissions[] = $permission->getNamespace();
        }
    }
    return $permissions;
}

Это предполагает, что у вас есть сущность MoRole, которая имеет смысл в отношении вашей текущей настройки, но вы ее не упомянули. В противном случае можно применить ту же логику, но это просто вопрос именования.

...