如何在 SQL 请求 API-Platform 中的 "GET item" 请求之前验证 UUID 参数?

How to validate the UUID parameter before SQL request for a "GET item" request in API-Platform?

使用:

我有一个具有以下 ID 的实体:

/**
 * @ORM\Entity(repositoryClass="App\Repository\ContractRepository")
 * @ORM\HasLifecycleCallbacks
 */
class Contract
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="UUID")
     * @ORM\Column(name="id", type="guid", unique=true)
     */
    private $id;
[...]

我使用 Api 平台生成以下路由:

App\Entity\Contract:
  itemOperations:
    get:

所以我得到了一条生成的路线 /contracts/{id}

目前,如果我 /contracts/TEST,它会尝试在 where 子句中使用“TEST”执行 SQL 请求,因此会失败,因为 500

我想通过断言 {id} 参数是 UUID_v4 和 return 如果不是 400 来防止这种行为。

此行为是特定于 DBMS 的,因此您必须添加自己的逻辑。

检索给定 ID 实体的 API-Platform 组件是 ItemDataProviderInterface

  1. 首先,我将声明一个新的异常MalformedUuidException
  2. 接下来我会convert this exception to a 400 error.
  3. 最后,我将创建一个新的 ItemDataProviderInterface 实现,包装 ORM 并向 ID 添加一些检查:
class ContractDataProvider implements RestrictedDataProviderInterface, ItemDataProviderInterface
{
    /** @var ItemDataProviderInterface */
    private $realDataProvider;

    public function __construct(ItemDataProviderInterface $realDataProvider)
    {
        $this->realDataProvider = $realDataProvider;
    }

    public function getItem(string $resourceClass, $id, string $operationName = null, array $context = [])
    {
        $uuidPattern = '/^[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$/i';
        if (preg_match($uuidPattern, $id) === 1) {
            return $this->realDataProvider->getItem($resourceClass, ['id' => $id], $operationName, $context);
        } else {
            throw new MalformedUuidException("the given ID \"$id\" is not a valid UUID.");
        }
    }

    public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
    {
        return $resourceClass === Contract::class;
    }
}
# config/services.yaml
    App\DataProvider\ContractDataProvider:
        arguments:
            $realDataProvider: '@api_platform.doctrine.orm.default.item_data_provider'

但是,请注意 getItem() 方法的契约没有指定 MalformedUuidException 异常,所以这个实现违反了 Liskov 替换原则。

考虑返回 null 并满足于 404 错误。