使用Symfony,如何根据用户角色查询实体?

时间:2016-12-08 16:46:15

标签: php entity-framework symfony doctrine-orm doctrine

我们说我有一个Book实体,其字段为$grantedTo,内容为用户角色。 此字段允许根据用户角色授予或拒绝对书籍的访问。

让我们考虑另一个名为Library的实体与OneToMany关系$books

现在从树枝上看,我想这样做:

{{ myLibrary.grantedBooks }}

grantedBooks方法会返回允许用户查看的所有图书馆图书。

但是要在我的类库中构建这样的方法,我需要调用像isGranted($book->grantedTo)这样的东西,我认为这是不可能的,因为我无法从我的实体中访问安全上下文

所以我想我应该提供一个服务,我会注入安全上下文,并从Twig访问这个服务。

我不确定这是最好的解决方案,并且很高兴听到其他可能性。

1 个答案:

答案 0 :(得分:1)

您可以在Library类中添加一个getter,如下所示:

public function getGrantedBook($role) {
    return array_filter($this->books, function(Book $book) use($role){
        return $book->getGrantedTo() == $role;
    });
}

在您的观点中,您需要将其传递给当前用户的角色。

修改

如果你需要处理具有高级角色的用户的情况,我建议使用一个doctrine实体监听器并将@ security.role_hierarchy和@token_storage注入其中,然后在onPostLoad事件中你可以放置你的逻辑:

<service id="my_bundle.library_listener" class="AppBundle\EntityListener\LibraryListener">
    <tag name="doctrine.orm.entity_listener" entity="AppBundle\Entity\Library" event="postLoad" />
    <argument type="service" id="security.token_storage" />
    <argument type="service" id="security.role_hierarchy" />
</service>

在你的听众中:

class LibraryListener {

    private $roleHierarchy;
    private $tokenStorage;

    //Constructor...

    /**
     * @param Library $library
     * @param LifecycleEventArgs $eventArgs
     */
    public function postLoad(Library $library, LifecycleEventArgs $eventArgs)
    {
        $currentUser = $this->tokenStorage->getToken()->getUser();
        $library->setGrantedBooks(array_filter($library->getBooks(), function($book) use($currentUser){
            return $this->isGranted($book, $currentUser);
        }));
    }

    /**
     * isGranted
     *
     * @param Book $book
     * @param $user
     * @return bool
     */
    private function isGranted($book, $user) {

        $role = new Role($book->getGrantedTo();

        foreach($user->getRoles() as $userRole) {
            if (in_array($role, $this->roleHierarchy->getReachableRoles(array(new Role($userRole)))))
                return true;
        }

        return false;
     }
}

显然,您需要在Library类中添加getGrantedBooks方法,希望这会有所帮助!