Api-platform中基于JWT用户筛选多对多关联Team集合的问题
实现方案
1. 确保实体关联配置正确
先确认User和Team的多对多关联配置无误(Team为关系拥有方):
User 实体
<?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity] class User { // ... 其他属性和方法 /** * @ORM\ManyToMany(targetEntity=Team::class, inversedBy="users") */ private $teams; // 构造函数、getter/setter 略 }
Team 实体
<?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity] class Team { // ... 其他属性和方法 /** * @ORM\ManyToMany(targetEntity=User::class, mappedBy="teams") * @ORM\JoinTable(name="user_team") // 若中间表名非默认可手动指定 */ private $users; // 构造函数、getter/setter 略 }
2. 编写自定义查询扩展类
创建CurrentUserTeamExtension类,通过API Platform的ORM扩展机制实现数据过滤,无需手动关联中间表(Doctrine会自动处理多对多的中间表关联逻辑):
<?php namespace App\ApiPlatform\Extension; use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use App\Entity\Team; use App\Entity\User; use Doctrine\ORM\QueryBuilder; use Symfony\Bundle\SecurityBundle\Security; final class CurrentUserTeamExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface { public function __construct(private readonly Security $security) { } public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null): void { $this->addUserFilter($queryBuilder, $resourceClass); } public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = []): void { $this->addUserFilter($queryBuilder, $resourceClass); } private function addUserFilter(QueryBuilder $queryBuilder, string $resourceClass): void { // 仅对Team实体生效,管理员角色跳过过滤(可根据需求调整) if ($resourceClass !== Team::class || $this->security->isGranted('ROLE_ADMIN')) { return; } $currentUser = $this->security->getUser(); if (!$currentUser instanceof User) { return; } $rootAlias = $queryBuilder->getRootAliases()[0]; // 通过Team的users关联自动关联中间表,生成符合预期的SQL逻辑 $queryBuilder->innerJoin(sprintf('%s.users', $rootAlias), 'u'); $queryBuilder->andWhere('u.id = :currentUserId'); $queryBuilder->setParameter('currentUserId', $currentUser->getId()); } }
3. 注册扩展服务
确保扩展类被Symfony容器识别,在config/services.yaml中添加标签(Symfony 6+ 若使用自动注册可省略,但手动添加更稳妥):
services: App\ApiPlatform\Extension\CurrentUserTeamExtension: tags: - { name: api_platform.doctrine.orm.query_extension.collection } - { name: api_platform.doctrine.orm.query_extension.item }
效果说明
配置完成后:
- 用户通过JWT登录后,
GET /teams接口仅返回该用户所属的团队 GET /teams/{id}接口会自动验证该团队是否属于当前用户(非管理员角色下),不属于则返回404
内容的提问来源于stack exchange,提问作者Hugo Trial
相关产品推荐
相关产品推荐

