AJAX 表单 post 上的 Symfony 419 状态错误
Symfony 419 status error on AJAX form post
我正在通过 AJAX post posting 一个 Symfony 表单,在我对“Siparis”实体和“SiparisType”中的相关表单字段进行字段编辑后,我保留了在 post.
上获得 419
Symfony 版本:6.0.2 - PHP version:8.1.2 数据库:10.4.22-MariaDB
我试图禁用 csrf 保护,但仍然得到相同的状态 419,除此之外什么都没有。
处理 AJAX post 的 Symfony 路由(我在编辑字段后恢复了我的最新更改,以下版本之前工作正常):
#[Route('/save/', name: 'save', methods: ['POST'])]
public function save_siparis(Request $request, EntityManagerInterface $entityManager): JsonResponse
{
$siparis = new Siparis();
try {
$form = $this->createForm(SiparisType::class, $siparis);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($siparis);
$entityManager->flush();
return new JsonResponse(['result' => 'OK', 'siparis_id' => $siparis->getId()]);
}
}catch(\Exception $e){
error_log($e->getMessage());
return new JsonResponse(array('result' => $e->getMessage()), 419);
}
}
控制器上的渲染表单路由:
唯一的变化是:'firma' => 本节中表单的 $id 选项
#[Route('/new/{id}', name: 'new', methods: ['GET'])]
public function new($id, Request $request, EntityManagerInterface $entityManager, SiparisRepository $siparisRepository,FirmaRepository $firmaRepository, IlgiliRepository $ilgiliRepository): Response
{
$siparis = new Siparis();
$latest_siparis = $siparisRepository->findBy(['Musteri' => $id], ['id' => 'desc', ]);
$siparis_id = 1;
if(!is_null($latest_siparis))
$siparis_id = count($latest_siparis) + 1;
$musteri = $firmaRepository->find($id);
$siparisNo = 'TST-'.str_replace(' ', '-',$musteri->getKod()).'-'.str_pad($siparis_id, 3, '0', STR_PAD_LEFT);
$form = $this->createForm(SiparisType::class, $siparis, ['firma' => $id,'attr' => ['id' => 'siparis_form']]);
$firmalar = $firmaRepository->findBy(['Type' => 0]);
$maliyet = new Maliyetler();
$maliyet_form = $this->createForm(MaliyetlerType::class, $maliyet, ['attr' => ['id' => 'maliyet_form']]);
return $this->renderForm('siparis/new.html.twig', [
'siparisNo' => $siparisNo,
'sipari' => $siparis,
'form' => $form,
'maliyet_form' => $maliyet_form,
'satici_firmalar' => $firmalar,
'musteri' => $musteri,
'mode' =>'NEW'
]);
}
我的表单类型:
字段:'siparis_veren' 是一个 TextType,我已将其更改为 EntityType,并通过查询生成器
获取相关实体
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$firma = $options['firma'];
$SIPARIS_CHOICES = ['Devam Ediyor' => '1','Tamamlandı' => '2','İptal' => '3'];
$builder
->add('teslim_tarihi', DateType::class, [
'widget' => 'single_text',
'label' => 'Teslim Tarihi', 'attr' =>['class' => 'form-control', 'placeholder' => 'Teslim Tarihi']
])
->add('siparis_tarihi', DateType::class, [
'widget' => 'single_text',
'label' => 'Sipariş Tarihi', 'attr' =>['class' => 'form-control', 'placeholder' => 'Sipariş Tarihi']
])
->add('siparis_veren', EntityType::class,['class' => Ilgili::class,
'choice_label' => 'full_name',
'query_builder' => function (EntityRepository $er) use ($firma) {
return $er->createQueryBuilder('ilgili')
->andWhere('ilgili.firma = :firma')
->setParameter('firma', $firma);
},
'label' => 'Siparişi Veren', 'attr' =>['class' => 'form-control', 'placeholder' => 'Siparişi Veren']])
->add('siparis_durum', ChoiceType::class,['choices' => $SIPARIS_CHOICES,'attr' =>['class' => 'form-control', 'placeholder' => 'Siparişi Alan'] ])
->add('siparis_turu', HiddenType::class)
->add('siparis_genel_aciklama', TextType::class,['label' => 'Sipariş Genel Açıklaması', 'attr' =>['class' => 'form-control', 'placeholder' => 'Sipariş Genel Açıklaması']])
->add('siparis_satir_aciklama', HiddenType::class)
->add('siparis_miktari', HiddenType::class)
->add('siparis_fiyati', HiddenType::class)
->add('fatura_durumu', HiddenType::class)
->add('siparisNo', HiddenType::class)
->add('siparis_kdv_orani', HiddenType::class);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Siparis::class,
'csrf_protection' => true,
'csrf_field_name' => '_token',
]);
$resolver->setRequired(['firma']);
}
我在客户端的AJAX表单post(这里没有变化):
$('form[name="siparis"]').submit(function(e) {
e.preventDefault();
var url = "{{ path('siparis_save') }}";
var formSerialize = $(this).serialize();
$.post(url, formSerialize, function(response) {
if(response.result === "OK")
{
$( 'form[name="maliyetler"]' ).submit();
}
else
{
console.log(response.result);
}
}, 'JSON');
});
在我的 Siparis 实体中 siparis_veren 是一个文本字段,我向它添加了一个与 Ilgili class 的 ManyToOne 关系,在我进行更改后 post 一直给我 419 错误。
#[ORM\ManyToOne(targetEntity: Ilgili::class, inversedBy: 'siparisler')]
#[ORM\JoinColumn(nullable: false)]
private $siparis_veren;
我尝试清除缓存,从表单类型和控制器中删除了相关的 siparis_veren 字段,但结果是一样的,除非我像以前一样将 siparis_veren 恢复为 TextType。
抱歉,如果我的解释还不够,我找不到关于这个问题的任何结果,SO 是我唯一的选择,我是 Symfony 的新手。
谢谢。
好的,我发现了问题,我没有注意到我在 Try Catch catch 块上将状态设置为 419,所以以为它是关于 Symfony 或客户端的。在进行了一些调试之后,我得到“解析表单选项时发生错误App\Form\SiparisType”:缺少必需的选项“firma”。
引起的错误
SiparisConroller.php
$form = $this->createForm(SiparisType::class, $siparis);
save_siparis() 函数中的这一行。在 SiparisType 中,我根据需要设置了 'firma' 字段
SiparisType.php
$resolver->setRequired(['firma']);
因此我在 Try Catch 块中遇到错误。
感谢@jean-max 对检查 Try Catch 的建议。
我正在通过 AJAX post posting 一个 Symfony 表单,在我对“Siparis”实体和“SiparisType”中的相关表单字段进行字段编辑后,我保留了在 post.
上获得 419Symfony 版本:6.0.2 - PHP version:8.1.2 数据库:10.4.22-MariaDB
我试图禁用 csrf 保护,但仍然得到相同的状态 419,除此之外什么都没有。 处理 AJAX post 的 Symfony 路由(我在编辑字段后恢复了我的最新更改,以下版本之前工作正常):
#[Route('/save/', name: 'save', methods: ['POST'])]
public function save_siparis(Request $request, EntityManagerInterface $entityManager): JsonResponse
{
$siparis = new Siparis();
try {
$form = $this->createForm(SiparisType::class, $siparis);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($siparis);
$entityManager->flush();
return new JsonResponse(['result' => 'OK', 'siparis_id' => $siparis->getId()]);
}
}catch(\Exception $e){
error_log($e->getMessage());
return new JsonResponse(array('result' => $e->getMessage()), 419);
}
}
控制器上的渲染表单路由: 唯一的变化是:'firma' => 本节中表单的 $id 选项
#[Route('/new/{id}', name: 'new', methods: ['GET'])]
public function new($id, Request $request, EntityManagerInterface $entityManager, SiparisRepository $siparisRepository,FirmaRepository $firmaRepository, IlgiliRepository $ilgiliRepository): Response
{
$siparis = new Siparis();
$latest_siparis = $siparisRepository->findBy(['Musteri' => $id], ['id' => 'desc', ]);
$siparis_id = 1;
if(!is_null($latest_siparis))
$siparis_id = count($latest_siparis) + 1;
$musteri = $firmaRepository->find($id);
$siparisNo = 'TST-'.str_replace(' ', '-',$musteri->getKod()).'-'.str_pad($siparis_id, 3, '0', STR_PAD_LEFT);
$form = $this->createForm(SiparisType::class, $siparis, ['firma' => $id,'attr' => ['id' => 'siparis_form']]);
$firmalar = $firmaRepository->findBy(['Type' => 0]);
$maliyet = new Maliyetler();
$maliyet_form = $this->createForm(MaliyetlerType::class, $maliyet, ['attr' => ['id' => 'maliyet_form']]);
return $this->renderForm('siparis/new.html.twig', [
'siparisNo' => $siparisNo,
'sipari' => $siparis,
'form' => $form,
'maliyet_form' => $maliyet_form,
'satici_firmalar' => $firmalar,
'musteri' => $musteri,
'mode' =>'NEW'
]);
}
我的表单类型: 字段:'siparis_veren' 是一个 TextType,我已将其更改为 EntityType,并通过查询生成器
获取相关实体public function buildForm(FormBuilderInterface $builder, array $options): void
{
$firma = $options['firma'];
$SIPARIS_CHOICES = ['Devam Ediyor' => '1','Tamamlandı' => '2','İptal' => '3'];
$builder
->add('teslim_tarihi', DateType::class, [
'widget' => 'single_text',
'label' => 'Teslim Tarihi', 'attr' =>['class' => 'form-control', 'placeholder' => 'Teslim Tarihi']
])
->add('siparis_tarihi', DateType::class, [
'widget' => 'single_text',
'label' => 'Sipariş Tarihi', 'attr' =>['class' => 'form-control', 'placeholder' => 'Sipariş Tarihi']
])
->add('siparis_veren', EntityType::class,['class' => Ilgili::class,
'choice_label' => 'full_name',
'query_builder' => function (EntityRepository $er) use ($firma) {
return $er->createQueryBuilder('ilgili')
->andWhere('ilgili.firma = :firma')
->setParameter('firma', $firma);
},
'label' => 'Siparişi Veren', 'attr' =>['class' => 'form-control', 'placeholder' => 'Siparişi Veren']])
->add('siparis_durum', ChoiceType::class,['choices' => $SIPARIS_CHOICES,'attr' =>['class' => 'form-control', 'placeholder' => 'Siparişi Alan'] ])
->add('siparis_turu', HiddenType::class)
->add('siparis_genel_aciklama', TextType::class,['label' => 'Sipariş Genel Açıklaması', 'attr' =>['class' => 'form-control', 'placeholder' => 'Sipariş Genel Açıklaması']])
->add('siparis_satir_aciklama', HiddenType::class)
->add('siparis_miktari', HiddenType::class)
->add('siparis_fiyati', HiddenType::class)
->add('fatura_durumu', HiddenType::class)
->add('siparisNo', HiddenType::class)
->add('siparis_kdv_orani', HiddenType::class);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Siparis::class,
'csrf_protection' => true,
'csrf_field_name' => '_token',
]);
$resolver->setRequired(['firma']);
}
我在客户端的AJAX表单post(这里没有变化):
$('form[name="siparis"]').submit(function(e) {
e.preventDefault();
var url = "{{ path('siparis_save') }}";
var formSerialize = $(this).serialize();
$.post(url, formSerialize, function(response) {
if(response.result === "OK")
{
$( 'form[name="maliyetler"]' ).submit();
}
else
{
console.log(response.result);
}
}, 'JSON');
});
在我的 Siparis 实体中 siparis_veren 是一个文本字段,我向它添加了一个与 Ilgili class 的 ManyToOne 关系,在我进行更改后 post 一直给我 419 错误。
#[ORM\ManyToOne(targetEntity: Ilgili::class, inversedBy: 'siparisler')]
#[ORM\JoinColumn(nullable: false)]
private $siparis_veren;
我尝试清除缓存,从表单类型和控制器中删除了相关的 siparis_veren 字段,但结果是一样的,除非我像以前一样将 siparis_veren 恢复为 TextType。
抱歉,如果我的解释还不够,我找不到关于这个问题的任何结果,SO 是我唯一的选择,我是 Symfony 的新手。
谢谢。
好的,我发现了问题,我没有注意到我在 Try Catch catch 块上将状态设置为 419,所以以为它是关于 Symfony 或客户端的。在进行了一些调试之后,我得到“解析表单选项时发生错误App\Form\SiparisType”:缺少必需的选项“firma”。
引起的错误SiparisConroller.php
$form = $this->createForm(SiparisType::class, $siparis);
save_siparis() 函数中的这一行。在 SiparisType 中,我根据需要设置了 'firma' 字段 SiparisType.php
$resolver->setRequired(['firma']);
因此我在 Try Catch 块中遇到错误。
感谢@jean-max 对检查 Try Catch 的建议。