如何在 SQL 请求 API-Platform 中的 "GET item" 请求之前验证 UUID 参数?
How to validate the UUID parameter before SQL request for a "GET item" request in API-Platform?
使用:
- PostgreSQL 11
uuid_generate_v4
类型
- Symfony 4.4.11
- Api 平台 2.5.6
我有一个具有以下 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。
- 首先,我将声明一个新的异常
MalformedUuidException
。
- 接下来我会convert this exception to a 400 error.
- 最后,我将创建一个新的 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 错误。
使用:
- PostgreSQL 11
uuid_generate_v4
类型 - Symfony 4.4.11
- Api 平台 2.5.6
我有一个具有以下 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。
- 首先,我将声明一个新的异常
MalformedUuidException
。 - 接下来我会convert this exception to a 400 error.
- 最后,我将创建一个新的 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 错误。