如何自定义API Platform默认操作,让登录用户仅查看关联车辆?
实现API Platform中登录用户仅获取关联车辆的两种方法
方法一:使用Doctrine ORM扩展(推荐)
这种方式会自动过滤所有Car集合查询,无需修改原有接口路径,是API Platform推荐的通用过滤方案。
步骤1:创建扩展类
在src/ApiPlatform/Extension目录下新建CarUserFilterExtension.php:
<?php namespace App\ApiPlatform\Extension; use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface; use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Metadata\Operation; use App\Entity\Car; use App\Entity\User; use Symfony\Component\Security\Core\Security; class CarUserFilterExtension implements QueryCollectionExtensionInterface { public function __construct(private readonly Security $security) { } public function applyToCollection(\Doctrine\ORM\QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { // 仅对Car实体的集合查询生效 if ($resourceClass !== Car::class) { return; } // 获取当前登录用户 $user = $this->security->getUser(); if (!$user instanceof User) { // 未登录时返回空结果,也可根据需求抛出401 $queryBuilder->andWhere('1 = 0'); return; } // 修改查询语句,过滤出与当前用户关联的车辆 $rootAlias = $queryBuilder->getRootAliases()[0]; $queryBuilder->join("$rootAlias.users", 'u') ->andWhere('u.id = :userId') ->setParameter('userId', $user->getId()); } }
说明
- 依赖Symfony的
Security服务获取当前登录用户 - 通过修改Doctrine查询构建器,自动为所有Car集合查询添加关联过滤条件
- 未登录用户会得到空结果,可根据业务需求调整为返回401未授权
方法二:自定义Get Collection操作
如果需要单独创建一个接口或完全替换默认的/api/cars接口逻辑,可以用自定义控制器的方式。
步骤1:修改Car实体的API配置
更新Car.php中的#[ApiResource]注解,添加自定义的集合查询操作:
#[ApiResource( security: 'is_granted("ROLE_USER")', // 限制仅登录用户访问 operations: [ // 替换默认的GET /api/cars接口 new GetCollection( uriTemplate: '/api/cars', controller: UserCarsController::class ), // 保留其他默认操作(按需调整) new Get(), new Post(), new Put(), new Delete() ] )] #[ORM\Entity(repositoryClass: CarRepository::class)] class Car { // ... 现有实体代码 // 记得为实体属性添加序列化组,确保返回格式正确 #[ORM\ManyToMany(targetEntity: User::class, inversedBy: 'cars')] #[ApiProperty(groups: ['car:read'])] private Collection $users; // 其他属性也需添加对应序列化组,例如: #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] #[ApiProperty(groups: ['car:read'])] private ?int $id = null; }
步骤2:创建自定义控制器
在src/Controller目录下新建UserCarsController.php:
<?php namespace App\Controller; use App\Entity\Car; use App\Entity\User; use Symfony\Component\Security\Core\Security; use Symfony\Component\HttpFoundation\JsonResponse; use ApiPlatform\Serializer\SerializerInterface; class UserCarsController { public function __construct( private readonly Security $security, private readonly SerializerInterface $serializer ) { } public function __invoke(): JsonResponse { $user = $this->security->getUser(); if (!$user instanceof User) { return new JsonResponse(['message' => '未授权'], 401); } // 直接获取用户关联的车辆集合 $cars = $user->getCars(); // 使用API Platform的序列化器保持返回格式与默认接口一致 $serializedData = $this->serializer->serialize( $cars, 'json', ['groups' => 'car:read'] ); return JsonResponse::fromJsonString($serializedData); } }
说明
- 自定义控制器直接从当前用户对象获取关联的车辆集合,逻辑更直观
- 需确保实体属性配置了正确的序列化组,否则返回的JSON会缺少字段
- 通过
security属性限制接口仅登录用户可访问
内容的提问来源于stack exchange,提问作者user18419618
相关产品推荐
相关产品推荐

