有没有办法在 Symfony 中使用表单发送 GET 请求并避免在更改 URL 时重新加载页面?
Is there a way to send a GET request using forms in Symfony and avoid reloading the page while changing the URL?
我有以下表格类型:
<?php
namespace Myproject\App\ErpBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormEvent;
use Myproject\OrderBundle\Entity\OrderProductType;
use Myproject\OrderBundle\Entity\OrderOrder;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\HttpFoundation\RequestStack;
class OrderSearchType extends AbstractType
{
protected $em;
protected $container;
protected $requestStack;
public function __construct(ObjectManager $em, ContainerInterface $container, RequestStack $requestStack)
{
$this->em = $em;
$this->container = $container;
$this->requestStack = $requestStack;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$data = $builder->getData();
$currentRequest = $this->requestStack->getCurrentRequest();
$pt = [
'class' => OrderProductType::class,
'choices' => [],
'required' => false
];
if ($productType = $currentRequest->query->get('ProductType', null)) {
$pt["data"] = $productType;
}
$id = [
'label' => 'id',
'required' => false
];
if ($idValue = $currentRequest->query->get('id', null)) {
$id["data"] = $idValue;
}
$name = [
'label' => 'név',
'required' => false
];
if ($nm = $currentRequest->query->get('name', null)) {
$name["data"] = $nm;
}
$builder
->add('productType', EntityType::class, $pt)
->add('id', IntegerType::class, $id)
->add('name', TextType::class, $name)
->add('status', ChoiceType::class, [
'choices' => [ 'Bármilyen',
OrderOrder::$ORDER_STATUS_TEXT[OrderOrder::$ORDER_STATUS_ORDERED],
OrderOrder::$ORDER_STATUS_TEXT[OrderOrder::$ORDER_STATUS_ACCEPTED],
OrderOrder::$ORDER_STATUS_TEXT[OrderOrder::$ORDER_STATUS_REFUSED]
],
'data' => $currentRequest->query->get('status', "1")
])
->add('search', SubmitType::class, [
'label' => 'Keresés',
'attr' => ['class' => 'btn btn-primary btn-sm']
]);
$builder->addEventListener(FormEvents::PRE_SUBMIT, array($this, 'onPresubmit'));
$builder->addEventListener(FormEvents::POST_SET_DATA, array($this, 'onPostSetData'));
}
public function onPostSetData(FormEvent $event)
{
$form = $event->getForm();
$data = $form->getData();
$event->getForm()
->add('productType', EntityType::class, [
'class' => OrderProductType::class,
'choices' => $this->em->getRepository(OrderProductType::class)->findAll(),
'choice_label' => function($orderProductType = null) {
return sprintf($orderProductType ? $orderProductType->getTitle() : "Kérem válasszon");
},
'label' => 'Termékfajta',
'required' => false,
'attr' => [
'class' => 'selectpicker',
'data-live-search' => 'true'
]
]);
}
public function onPresubmit(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
$event->getForm()
->add('productType', EntityType::class, [
'class' => OrderProductType::class,
'choices' => $this->em->getRepository(OrderProductType::class)->findAll(),
'choice_label' => function($orderProductType = null) {
return sprintf($orderProductType ? $orderProductType->getTitle() : "Kérem válasszon");
},
'label' => 'Termékfajta',
'required' => false,
'attr' => [
'class' => 'selectpicker',
'data-live-search' => 'true'
]
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => null,
'em' => $this->em,
]);
parent::configureOptions($resolver);
}
public function getBlockPrefix()
{
return 'route';
}
}
在ui上显示是这样的:
{{ form_start(form, { 'attr': {'class': 'myprojectAdminForm pull-right', 'id': form.vars.name } }) }}
Szűrés:
{{ form_widget(form.productType) }}
{{ form_widget(form.id, {'attr': {'placeholder': form.id.vars.label, 'class':'form-control'}}) }}
{{ form_widget(form.name, {'attr': {'placeholder': form.name.vars.label, 'class':'form-control' }}) }}
{{ form_widget(form.status, {'attr': {'class':'form-control'}}) }}
{{ form_widget(form.search) }}
{{ form_widget(form._token) }}
{{ form_errors(form) }}
{{ form_end(form, {'render_rest': false}) }}
每当用户点击搜索时,就会执行以下 Javascript:
$("#erpordersearch_search").click(function(e) {
e.preventDefault();
var productTypeID = document.querySelector("#erpordersearch_productType").value;
var ID = document.getElementById("erpordersearch_id").value;
var name = document.getElementById("erpordersearch_name").value;
var status = document.getElementById("erpordersearch_status").value;
var url = window.location.href.substring(0, window.location.href.lastIndexOf("/page"));
url = url + "/page1";
window.location.href = url + "[ProductTypeID=" + productTypeID + "&id=" + ID + "&name=" + name + "&status=" + status + "]";
});
这行得通,但问题是我在 ui 上跟踪用户操作历史,如果系统加载了整个页面,那么我将丢失所有用户操作历史,因为历史保存在Javascript中。我知道我可以将历史记录保存在数据库或 localStorage
中,但在我的情况下,这两者都不是可行的选择,因为它们会违反项目的政策。我被要求进行修改,其中包含以下功能:
- URL在请求响应后会包含
[queryString=somevalue]
,即使在GET请求 之前不包含[queryString=somevalue]
- 请求后,所有定义的 Javascript 变量都应该存在。如果我在控制台中写了
var foo = 'bar';
,在请求之后应该定义变量
关于如何通过 Symfony 和我正在从事的特定项目的组合来实现这一点,我得到了一些模糊的描述,但它不清楚并且包含我无法在此处分享的特定于项目的信息。
所以我的问题是:有没有办法使用 PHP 和 Symfony,在发送请求时更改 URL 并仍然保留在 Javascript 中定义的所有变量?
我认为这是可能的唯一方法(准备更模糊的解释)是将您的 JavaScript 变量存储在按下搜索按钮时提交的不可见表单元素中。
然后这些应该通过 post 数据发送到 Symfony 控制器,然后您可以使用此处概述的方法将变量从 PHP 发送到 JavaScript(但已修改对于树枝语法)- How can I store JavaScript variable output into a PHP variable?
如果在脚本文件中,您可以尝试以这种方式传递参数 - https://www.gun.io/blog/pass-arguments-to-embedded-javascript-tutorial-example
编辑
再次阅读所有内容(并在下面的评论中讨论)后,我想我更好地理解了这个问题。
我个人同意你的看法,这看起来不可能在纯 Symfony 中通过 GET 请求来完成。
即使有 "hacky" 方法,它也不是可扩展的或动态的,因此不值得做。
我有以下表格类型:
<?php
namespace Myproject\App\ErpBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormEvent;
use Myproject\OrderBundle\Entity\OrderProductType;
use Myproject\OrderBundle\Entity\OrderOrder;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\HttpFoundation\RequestStack;
class OrderSearchType extends AbstractType
{
protected $em;
protected $container;
protected $requestStack;
public function __construct(ObjectManager $em, ContainerInterface $container, RequestStack $requestStack)
{
$this->em = $em;
$this->container = $container;
$this->requestStack = $requestStack;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$data = $builder->getData();
$currentRequest = $this->requestStack->getCurrentRequest();
$pt = [
'class' => OrderProductType::class,
'choices' => [],
'required' => false
];
if ($productType = $currentRequest->query->get('ProductType', null)) {
$pt["data"] = $productType;
}
$id = [
'label' => 'id',
'required' => false
];
if ($idValue = $currentRequest->query->get('id', null)) {
$id["data"] = $idValue;
}
$name = [
'label' => 'név',
'required' => false
];
if ($nm = $currentRequest->query->get('name', null)) {
$name["data"] = $nm;
}
$builder
->add('productType', EntityType::class, $pt)
->add('id', IntegerType::class, $id)
->add('name', TextType::class, $name)
->add('status', ChoiceType::class, [
'choices' => [ 'Bármilyen',
OrderOrder::$ORDER_STATUS_TEXT[OrderOrder::$ORDER_STATUS_ORDERED],
OrderOrder::$ORDER_STATUS_TEXT[OrderOrder::$ORDER_STATUS_ACCEPTED],
OrderOrder::$ORDER_STATUS_TEXT[OrderOrder::$ORDER_STATUS_REFUSED]
],
'data' => $currentRequest->query->get('status', "1")
])
->add('search', SubmitType::class, [
'label' => 'Keresés',
'attr' => ['class' => 'btn btn-primary btn-sm']
]);
$builder->addEventListener(FormEvents::PRE_SUBMIT, array($this, 'onPresubmit'));
$builder->addEventListener(FormEvents::POST_SET_DATA, array($this, 'onPostSetData'));
}
public function onPostSetData(FormEvent $event)
{
$form = $event->getForm();
$data = $form->getData();
$event->getForm()
->add('productType', EntityType::class, [
'class' => OrderProductType::class,
'choices' => $this->em->getRepository(OrderProductType::class)->findAll(),
'choice_label' => function($orderProductType = null) {
return sprintf($orderProductType ? $orderProductType->getTitle() : "Kérem válasszon");
},
'label' => 'Termékfajta',
'required' => false,
'attr' => [
'class' => 'selectpicker',
'data-live-search' => 'true'
]
]);
}
public function onPresubmit(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
$event->getForm()
->add('productType', EntityType::class, [
'class' => OrderProductType::class,
'choices' => $this->em->getRepository(OrderProductType::class)->findAll(),
'choice_label' => function($orderProductType = null) {
return sprintf($orderProductType ? $orderProductType->getTitle() : "Kérem válasszon");
},
'label' => 'Termékfajta',
'required' => false,
'attr' => [
'class' => 'selectpicker',
'data-live-search' => 'true'
]
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => null,
'em' => $this->em,
]);
parent::configureOptions($resolver);
}
public function getBlockPrefix()
{
return 'route';
}
}
在ui上显示是这样的:
{{ form_start(form, { 'attr': {'class': 'myprojectAdminForm pull-right', 'id': form.vars.name } }) }}
Szűrés:
{{ form_widget(form.productType) }}
{{ form_widget(form.id, {'attr': {'placeholder': form.id.vars.label, 'class':'form-control'}}) }}
{{ form_widget(form.name, {'attr': {'placeholder': form.name.vars.label, 'class':'form-control' }}) }}
{{ form_widget(form.status, {'attr': {'class':'form-control'}}) }}
{{ form_widget(form.search) }}
{{ form_widget(form._token) }}
{{ form_errors(form) }}
{{ form_end(form, {'render_rest': false}) }}
每当用户点击搜索时,就会执行以下 Javascript:
$("#erpordersearch_search").click(function(e) {
e.preventDefault();
var productTypeID = document.querySelector("#erpordersearch_productType").value;
var ID = document.getElementById("erpordersearch_id").value;
var name = document.getElementById("erpordersearch_name").value;
var status = document.getElementById("erpordersearch_status").value;
var url = window.location.href.substring(0, window.location.href.lastIndexOf("/page"));
url = url + "/page1";
window.location.href = url + "[ProductTypeID=" + productTypeID + "&id=" + ID + "&name=" + name + "&status=" + status + "]";
});
这行得通,但问题是我在 ui 上跟踪用户操作历史,如果系统加载了整个页面,那么我将丢失所有用户操作历史,因为历史保存在Javascript中。我知道我可以将历史记录保存在数据库或 localStorage
中,但在我的情况下,这两者都不是可行的选择,因为它们会违反项目的政策。我被要求进行修改,其中包含以下功能:
- URL在请求响应后会包含
[queryString=somevalue]
,即使在GET请求 之前不包含 - 请求后,所有定义的 Javascript 变量都应该存在。如果我在控制台中写了
var foo = 'bar';
,在请求之后应该定义变量
[queryString=somevalue]
关于如何通过 Symfony 和我正在从事的特定项目的组合来实现这一点,我得到了一些模糊的描述,但它不清楚并且包含我无法在此处分享的特定于项目的信息。
所以我的问题是:有没有办法使用 PHP 和 Symfony,在发送请求时更改 URL 并仍然保留在 Javascript 中定义的所有变量?
我认为这是可能的唯一方法(准备更模糊的解释)是将您的 JavaScript 变量存储在按下搜索按钮时提交的不可见表单元素中。
然后这些应该通过 post 数据发送到 Symfony 控制器,然后您可以使用此处概述的方法将变量从 PHP 发送到 JavaScript(但已修改对于树枝语法)- How can I store JavaScript variable output into a PHP variable?
如果在脚本文件中,您可以尝试以这种方式传递参数 - https://www.gun.io/blog/pass-arguments-to-embedded-javascript-tutorial-example
编辑
再次阅读所有内容(并在下面的评论中讨论)后,我想我更好地理解了这个问题。
我个人同意你的看法,这看起来不可能在纯 Symfony 中通过 GET 请求来完成。
即使有 "hacky" 方法,它也不是可扩展的或动态的,因此不值得做。