Symfony:如何根据登录用户的角色在路由上添加序列化程序组

Symfony: how to add a serializer group on a Route depending on logged in user's roles

我在我的实体定义中使用 JMSSerializerBundle,在控制器中使用 RestBundle 的注释。

我有一个具有 public 和管理员保护属性的实体,比方说

use JMS\Serializer\Annotation as Serializer;

class UserAddress {
    /**
     * @Serializer\Expose
     * @Serializer\Groups(groups={"address:read"})
     */
    private $nonSecretAttribute;

    /**
     * @Serializer\Expose
     * @Serializer\Groups(groups={"address:admin-read"})
     */
    private $secretAttribute;
}

还有一个用户喜欢:

class User {
    // ...
    
    /**
     * @ORM\OneToMany(targetEntity="UserAddress", mappedBy="user")
     */
    private $addresses;

我的控制器看起来像

use FOS\RestBundle\Controller\Annotations as Rest;

class UsersController {
    /**
     * @Rest\Get("/users/{user}/addresses", requirements={"user"="\d+"})
     * @Rest\View(serializerGroups={"address:read"})
     * @IsGranted("user_read", subject="user")
     */
    public function getUsersAddresses(User $user)
    {
        return $user->getAddresses();
    }
}

但是如果登录用户恰好具有 ADMIN_ROLE 角色,我如何将 address:admin-read 添加到此处的序列化程序组? 在 @Rest\View 注释中可能吗? 我是否有办法修改控制器方法中的组,在条件循环中验证我登录的用户的角色?

您应该手动实例化 fos-rest View 并添加一个 Context。在那个 Context 上,您可以通过评估用户角色在运行时设置序列化组。

像这样的东西应该可以工作:

use FOS\RestBundle\View\View;
use FOS\RestBundle\Context\Context;

class UsersController 
{

    public function getUsersAddresses(User $user): View
    {
        $isAdmin = in_array('ROLE_ADMIN', $user->getRoles());
        $context = new Context();
        $context->setGroups($isAdmin ? ['address:admin-read'] : ['address:read']);

        $view = VVV::create()->setContext($context);


        return $view
            ->setContext($context)
            ->setData($user->getAddresses());
    }
}