搜尋

首頁  >  問答  >  主體

Symfony POST 請求正在通過驗證,但它應該會給出錯誤

訂單模型.php

<?php

namespace App\Dto\Request\Model;

use Symfony\Component\Validator\Constraints as Assert;

class OrderModel
{
    #[Assert\Uuid(message: "Order id must be an unique identifier value.")]
    #[Assert\Positive(message: "Order id must be a positive integer value.")]
    public int $id;

    /**
     * @Assert\Positive(message="customerId must be a positive integer value.")
     */
    public int $customerId;

    public array $items;

    /**
     * @Assert\Type("string", message="Order total must be a string float value.")
     * @Assert\Type("float", message="Order total must be a string float value.")
     */
    public string $total;
}

訂單類型.php

<?php

use App\Dto\Request\Model\OrderModel;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class OrderType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('id', IntegerType::class)
            ->add('customerId', IntegerType::class)
            ->add('items', CollectionType::class, [
                'entry_type' => ItemType::class
            ])
            ->add('total', TextType::class);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => OrderModel::class
        ]);
    }
}

OrderController.php:

#[Route('/order', name:'order_new', methods: 'POST')]
public function create(ManagerRegistry $doctrine, Request $request): JsonResponse|Response
{
    $form = $this->createForm(\OrderType::class);
    if ($request->isMethod('POST')) {
        $form->submit($request->request->get($form->getName()));
        if(!$form->isSubmitted() || !$form->isValid()){
            return $this->handleView($this->view($form, Response::HTTP_BAD_REQUEST));
        }
    }
}

我的貼文請求:

{
  "id": "dsdas",
  "customerId": 1,
  "items": [
      {
          "productId": 1,
          "quantity": 1,
          "unitPrice": "250.25",
          "total": "250.25"
      },
      {
          "productId": 1,
          "quantity": 1,
          "unitPrice": "250.25",
          "total": "250.25"
      }
  ],
  "total": "500.50"
}

此請求正在通過驗證,我正在嘗試弄清楚。任何想法將不勝感激。

P粉231079976P粉231079976312 天前458

全部回覆(1)我來回復

  • P粉327903045

    P粉3279030452024-03-30 12:25:10

    我認為您在提交的資料中缺少表單名稱作為頂級鍵。您正在嘗試發送此內容:

    {
        "id": "dsdas",
        "customerId": 1,
        "total": "500.50"
    }

    您的程式碼 ($request->request->get($form->getName())) 期望這樣(如果表單名稱是「order_type」)

    {
        "order_type": {
            "id": "dsdas",
            "customerId": 1,
            "total": "500.50"
        }
    }

    一個解決方案是建立一個命名表單...沒有名稱:)

    public function create(
        Request $request,
        FormFactoryInterface $formFactory
    ) {
        // Create form with no name: setting the first parameter to '' means no name (ideal for API endpoints)
        $form = $formFactory->createNamed('', OrderType::class);
        $form->handleRequest($request);
        if(
            !$form->isSubmitted() ||
            !$form->isValid()
        ) {
            // ...
        } else {
            // ...
        }
    }

    第二種解決方案是自己新增表單名稱

    public function create(Request $request): JsonResponse|Response
    {
        $form = $this->createForm(\OrderType::class);
        if ($request->isMethod('POST')) {
            $form->submit([
                // You can also add the key yourself right before submitting
                $form->getName() => $request->request->all(),
            ]);
            if(
                !$form->isSubmitted() ||
                !$form->isValid()
            ){
                return $this->handleView($this->view($form, Response::HTTP_BAD_REQUEST));
            }
        }
    }

    第三個選項(但不是最好的選項)是您始終將資料與表單金鑰一起傳送到控制器,但如果它是 API 端點,我不會選擇此選項。所以只有當是常規表單提交且提交的表單欄位全部以原始表單名稱前綴產生時。

    作為最後一個選項,您也可以擷取傳入的兩種資料格式。也許類似這樣,您實際上可以使用或不使用金鑰進行發送:

    $finalData = $request->request->get($form->getName()) ?: $request->request->all();
    $form->submit([$form->getName() => $finalData]);

    回覆
    0
  • 取消回覆