Есть ли способ отправить запрос GET с помощью форм в Symfony и избежать перезагрузки страницы при изменении 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';
    }
}

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

            {{ 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?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
197
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

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


РЕДАКТИРОВАТЬ

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

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

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

Я понимаю ваш ответ, но если я это реализую, он не будет принят. Ожидается, что при поиске будет получен запрос GET, который изменит URL-адрес и изменит содержимое страницы без полной перезагрузки. Насколько мне известно, URL-адрес не может быть изменен без перезагрузки страницы (за исключением изменения хэша, что здесь не вариант). Если я прав в том, что это невозможно, то я могу сказать другим, что их идея невозможна. Если есть возможность, я должен это реализовать.

Lajos Arpad 04.07.2018 18:16

В этом проекте Symfony есть хлебная крошка, и всякий раз, когда мы щелкаем ссылку, она раскрывается. Однако, если мы нажмем на ссылку хлебных крошек, данная страница должна загрузиться без полной загрузки страницы. Если URL-адрес не содержит того, что мне нужно, история будет потеряна. Я могу реализовать хаки, но они не будут приняты, пока я не докажу, что первоначальная идея невозможна.

Lajos Arpad 04.07.2018 18:18

@LajosArpad думали ли вы о том, чтобы просто изменить URL-адрес в Javascript и использовать что-то вроде vue.js для отображения результатов с помощью JSON? Связанный вопрос об изменении URL - stackoverflow.com/questions/824349/…

Hex 06.07.2018 17:01

Меня не интересует VueJS в контексте этого вопроса, однако предоставленная вами ссылка отвечает на суть этого вопроса. Поскольку это вопрос Symfony, нам нужно знать, есть ли в Symfony что-то, что отвечает за такое поведение.

Lajos Arpad 07.07.2018 15:22

@LajosArpad, насколько я понимаю PHP и Java, это не проблема Symfony, а просто фундаментальный способ работы сети (если я правильно понимаю ваш вопрос), поскольку Java является клиентской, а Symfony - серверной, нет ничего вы можете изменить любой из них, чтобы удалить это поведение, поскольку оно не вызвано ни тем, ни другим. Вам понадобится «хакерское» решение или взгляните на JSON-фреймворки, чтобы решить эту проблему.

Hex 09.07.2018 20:32

Под «Java», я полагаю, вы имели в виду Javascript. Symfony - это большой набор инструментов, который предоставляет множество инструментов. Если я начну использовать инструмент вне Symfony, тогда как Symfony предоставляет эквивалентный инструмент для того же, тогда мое решение не будет принято. Вы указали, что эта функция возможна, и рекомендовали VueJS, однако VueJS не подходит, если для этого нет решения на основе Symfony. Symfony предоставляет фреймворк на стороне сервера, но это не исключает возможности предоставления функций на стороне клиента.

Lajos Arpad 10.07.2018 13:16

Подробнее о клиентских функциях Symfony читайте здесь: symfony.com/doc/current/frontend.html

Lajos Arpad 10.07.2018 13:17

@lajosarpad, однако, даже те функции, с которыми вы связались, технически не являются «клиентской стороной», поскольку они всего лишь оболочки для обслуживания контента клиенту и управления активами. Прочитав все это еще раз, я думаю, что лучше понимаю вопрос. Я лично согласен с вами, похоже, это невозможно сделать в чистом Symfony через GET-запросы. Даже если бы существовал «хакерский» метод, он не был бы масштабируемым или динамичным.

Hex 10.07.2018 14:25

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

Lajos Arpad 11.07.2018 11:13

Другие вопросы по теме