我是 Symfony 5.4 的新手,最近使用該版本創建了我的第一個 API
對于我的特定 API 端點,其中一個引數是 ID 陣列。
我需要通過以下方式驗證此陣列:
- 確保這是一個陣列;
- 確保陣列中的 ID 實際上是指資料庫記錄;
我以一種直接的方式實作了它,在使用型別轉換和 existing 持久化物體之前檢查陣列Repository:
$parentPropertyIds = (array)$request->request->get('parent_property_ids');
if ($parentPropertyIds) {
$parentCount = $doctrine->getRepository(Property::class)->countByIds($parentPropertyIds);
if ($parentCount !== count($parentPropertyIds)) {
return $this->json([
'status' => 'error',
'message' => 'parent_property_id_invalid'
], 422);
}
foreach ($parentPropertyIds as $parentPropertyId) {
$parentProperty = $doctrine->getRepository(Property::class)->find($parentPropertyId);
$property->addParent($parentProperty);
}
}
然而,這使我的控制器動作變得過于“身體積極”并且感覺可以以更優雅的方式實作。
我無法在 Symfony 5.4 檔案中找到任何內容。
目前我想知道是否:
- 在 Symfony 中有一種過濾/清理請求引數的方法;
- 有一種優雅的內置方式可以將自定義驗證器約束應用于請求引數(類似于有據可查的物體欄位驗證);
完整端點代碼:
/**
* @Route("/property", name="property_new", methods={"POST"})
*/
public function create(ManagerRegistry $doctrine, Request $request, ValidatorInterface $validator): Response
{
$entityManager = $doctrine->getManager();
$property = new Property();
$property->setName($request->request->get('name'));
$property->setCanBeShared((bool)$request->request->get('can_be_shared'));
$parentPropertyIds = (array)$request->request->get('parent_property_ids');
if ($parentPropertyIds) {
$parentCount = $doctrine
->getRepository(Property::class)
->countByIds($parentPropertyIds);
if ($parentCount !== count($parentPropertyIds)) {
return $this->json([
'status' => 'error',
'message' => 'parent_property_id_invalid'
], 422);
}
foreach ($parentPropertyIds as $parentPropertyId) {
$parentProperty = $doctrine->getRepository(Property::class)->find($parentPropertyId);
$property->addParent($parentProperty);
}
}
$errors = $validator->validate($property);
if (count($errors) > 0) {
$messages = [];
foreach ($errors as $violation) {
$messages[$violation->getPropertyPath()][] = $violation->getMessage();
}
return $this->json([
'status' => 'error',
'messages' => $messages
], 422);
}
$entityManager->persist($property);
$entityManager->flush();
return $this->json([
'status' => 'ok',
'id' => $property->getId()
]);
}
uj5u.com熱心網友回復:
您可以結合使用資料傳輸物件 (DTO) 和驗證服務。有許多預定義約束,或者您可以創建自定義約束。
例如,如何使用簡單約束作為注釋:
class PropertyDTO {
/**
* @Assert\NotBlank
*/
public string $name = "";
public bool $shared = false;
}
然后將資料賦值給DTO:
$propertyData = new PropertyDTO();
$propertyData->name = $request->request->get('name');
...
在某些情況下,在 DTO 中定義建構式是個好主意,然后從請求中獲取所有資料并立即將其傳遞給 DTO:
$data = $request->getContent(); // or $request->getArray(); depends on your content type
$propertyData = new PropertyDTO($data);
然后驗證它:
$errors = $validator->validate($propertyData);
if (count($errors) > 0) {
/*
* Uses a __toString method on the $errors variable which is a
* ConstraintViolationList object. This gives us a nice string
* for debugging.
*/
$errorsString = (string) $errors;
return $this->json([
'status' => 'error',
'message' => 'parent_property_id_invalid'
], 422);
}
//...
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/533868.html
上一篇:Laravel發送郵件
