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

ApiPlatform+Symfony自定义URL参数被识别为标识符致NotFoundHttpException

解决ApiPlatform自定义路径参数被误识别为标识符的问题

1. 修正ApiResource操作配置

ApiPlatform 默认会把 URI 模板中的变量当作资源的标识符(比如实体的ID),所以需要显式声明tenant是自定义参数而非标识符。修改GetCollection操作,添加uriVariables配置:

#[ApiResource(
    operations: [
        new GetCollection(
            uriTemplate: '/{tenant}/agreement',
            uriVariables: [
                'tenant' => new UriVariable(
                    // 声明该变量不是资源标识符,无需匹配实体
                    identifier: false,
                    // 可选:指定参数类型
                    schema: new Type(type: Type::STRING)
                )
            ],
            openapi: new Model\Operation(
                parameters: [
                    new Model\Parameter(
                        name: 'tenant',
                        in: 'path',
                        required: true,
                        schema: new Type(type: Type::STRING)
                    ),
                ],
            ),
        ),
    ]
)]

2. 将参数注入SQL查询

要把tenant参数加入查询条件,推荐使用ApiPlatform的Doctrine ORM扩展,无需编写自定义控制器:

步骤1:创建查询扩展类

// src/Doctrine/Extension/TenantFilterExtension.php
namespace App\Doctrine\Extension;

use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use App\Entity\Agreement;
use Doctrine\ORM\QueryBuilder;

class TenantFilterExtension implements QueryCollectionExtensionInterface
{
    public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void
    {
        // 仅对Agreement资源和目标GetCollection操作生效
        if ($resourceClass !== Agreement::class || $operation?->getName() !== 'get_collection') {
            return;
        }

        // 从请求上下文获取tenant参数
        $tenant = $context['request']->get('tenant');
        if (!$tenant) {
            return;
        }

        // 添加tenant过滤条件
        $rootAlias = $queryBuilder->getRootAliases()[0];
        $queryBuilder->andWhere(sprintf('%s.tenant = :tenant', $rootAlias))
            ->setParameter('tenant', $tenant);
    }
}

步骤2:注册扩展类

在config/services.yaml中注册该服务:

services:
    App\Doctrine\Extension\TenantFilterExtension:
        tags:
            - { name: api_platform.doctrine.orm.query_extension.collection }

3. 验证效果

现在请求/指定租户值/agreement时,ApiPlatform会正确识别tenant为路径参数,不会再抛出NotFoundHttpException,同时查询会自动带上tenant的过滤条件。


内容的提问来源于stack exchange,提问作者atmacola

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 07:15:58