Symfony 4:Doctrine-entity returns 基于 ROLE_* 的不同数据

Symfony 4: Doctrine-entity returns different data based on ROLE_*

我得到了一个 Account 实体,它应该 return 基于当前登录用户角色的不同数据:

return [                                     // to be returned if user has role:
    'id' => $this->id,                       // ROLE_USER, ROLE_PAYED, ROLE_ADMIN
    'name' => $this->name,                   // ROLE_USER, ROLE_PAYED, ROLE_ADMIN
    'hobbies' => ['some', 'tags'],           // ROLE_PAYED, ROLE_ADMIN
    'roles' => ['ROLE_USER', 'ROLE_PAYED']   // ROLE_ADMIN
];

如果我要在控制器中进行此更改,我只需调用一个 voter. But I would like to use it inside the entity's jsonSerialize 函数,以便在每个请求中无一例外地实现它。

我猜真正的问题是 "how to get a voter inside an entity",但我对 Symfony 的了解其实还不够(现在只用了 10 天)。

选民是服务,服务真的不应该在实体内部。实体不应该对视图或控制器中的任何内容有任何了解。如果您发现自己需要实体内部的服务,这通常表明您需要重新考虑您的架构。

我将采用的方法是创建一个 JsonSerializeAccount 服务,该服务使用 AuthorizationChecker 创建 json 数组。

<?php

namespace App\Service;

use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use App\Entity\Account;

class JsonSerializeAccount {
    /**
     * @var AuthorizationCheckerInterface
     */
    private $authorizationChecker;

    public function __construct(AuthorizationCheckerInterface $authorizationChecker)
    {
        $this->authorizationChecker = $authorizationChecker;
    }

    public function jsonSerialize(Account $account): array
    {
        $json = [
            'id' => $account->getId(),
            'name' => $account->getName(),
        ];

        if ($this->authorizationChecker->isGranted('view_hobbies', $account)) {
            $json['hobbies'] = $account->getHobbies();
        }

        if ($this->authorizationChecker->isGranted('view_roles', $account)) {
            $json['roles'] = $account->getRoles();
        }

        return $json;
    }
}