You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 01:35:16