Symfony 4 Doctrine объединяет несколько таблиц в одном свойстве

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

mo_user

id   |    email      |   password
__________________________________
9144 | [email protected]  |   !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');
    }
}

Итак, я понял необработанный 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;

person Sanjok Gurung    schedule 11.05.2018    source источник


Ответы (2)


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

Однако вы можете добиться того, чего хотите, с помощью одного из этих решений:

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

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

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

например для последнего пункта:

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

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

person Aurelien    schedule 11.05.2018
comment
Спасибо, я попробую, у меня есть организация MoRole. Спасибо - person Sanjok Gurung; 11.05.2018
comment
Спасибо, для меня последний пункт был самым простым в реализации. отметил как правильный ответ. - person Sanjok Gurung; 11.05.2018
comment
Рад, что устранил вашу проблему. Имейте в виду другие способы для будущей работы. - person Aurelien; 11.05.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);
person qooplmao    schedule 12.05.2018