Есть ли способ отправить запрос GET с помощью форм в Symfony и избежать перезагрузки страницы при изменении URL? - PullRequest
0 голосов
/ 04 июля 2018

У меня есть следующий тип формы:

<?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';
    }
}

Отображается на интерфейсе следующим образом:

            {{ 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 + "]";
    });

Это работает, но проблема в том, что я отслеживаю историю действий пользователя в пользовательском интерфейсе, и если система загружает полную страницу, я теряю всю историю действий пользователя, так как история сохраняется в Javascript. Я знаю, что могу сохранить историю в базе данных или localStorage, но в моем случае любой из этих вариантов не является жизнеспособным, поскольку они нарушают политику проекта. Меня попросили сделать модификации, которые будут состоять из следующих функций:

  • URL будет содержать [queryString=somevalue] после ответа на запрос, даже если он не содержал его до запроса GET
  • после запроса все определенные переменные Javascript должны существовать. Если я написал var foo = 'bar'; в консоли, после запроса переменная должна быть определена

Мне дали какое-то расплывчатое описание того, как этого можно достичь с помощью Symfony и конкретного проекта, над которым я работаю, но оно неясно и содержит информацию по конкретному проекту, которой я не могу поделиться здесь.

Итак, мой вопрос: есть ли способ с помощью PHP и Symfony изменить URL при отправке запроса и при этом сохранить все переменные, которые были определены в Javascript?

1 Ответ

0 голосов
/ 04 июля 2018

Единственный способ, которым я бы сказал, что это возможно (подготовьтесь к более расплывчатым объяснениям), - это сохранить ваши переменные JavaScript в невидимых элементах формы, которые передаются при нажатии кнопки поиска.

Затем они должны быть отправлены на контроллер Symfony с помощью данных поста, здесь вы можете использовать описанный здесь метод для отправки переменных в JavaScript из PHP (но с измененным синтаксисом ветки) - Как сохранить переменную JavaScript вывод в переменную PHP?

Если в файле сценария вы можете попробовать передать аргументы таким образом - https://www.gun.io/blog/pass-arguments-to-embedded-javascript-tutorial-example


EDIT

Прочитав все это снова (и обсудив это в комментариях ниже), я думаю, что понимаю вопрос лучше.

Я лично с вами согласен, похоже, что это невозможно сделать в чистом Symfony с помощью запросов GET.

Даже если бы существовал «хакерский» метод, он не был бы масштабируемым или динамичным и, следовательно, не стоил делать.

...