Symfony Как в симфони2 разбить заполнение формы на несколько шагов?

alexmixaylov

Новичок
Столкнулся с задачей непосильной для себя, только учу симфони
процесс заказа разбит на несколько шагов
нужно как то сохранить данные с первых шагов и передать их в последующие
как это можно было бы сделать?
без использования дополнительных бандлов(там не нужна сложная логика)
PHP:
<?php
namespace AppBundle\Controller;

use Symfony\Component\DomCrawler\Field\ChoiceFormField;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; //под вопросом
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

use Symfony\Component\Form\Extension\Core\Type\DateTimeType;

use AppBundle\Entity\Book;
use AppBundle\Form\BookType;
use Symfony\Component\HttpFoundation\Response;


class BookController extends Controller
{
    /**
     * @Route("/")
     */
    public function findAction(Request $request)
    {

        $book = new Book();

        //шаг первый - запоняем начальные поля
        $form = $this->createFormBuilder($book)
            ->add('date', DateTimeType::class, array('widget' => 'single_text'))
            ->add('fromBook', ChoiceType::class)
            ->add('toBook', ChoiceType::class)
            ->add('returnDate', DateTimeType::class, array('widget' => 'single_text'))
            ->add('returnFrom', ChoiceType::class)
            ->add('returnTo', ChoiceType::class)
            ->add('people')
            ->add('isReturn', CheckboxType::class)
            ->getForm();

        $form->handleRequest($request);

        if ($form->isSubmitted()) {

            // после отправки формы
            // здесь как то нужно записать наверное данные из формы
            // чтобы можно было использовать эти данные в следующем getcarsAction

            return $this->redirectToRoute('/step2');
        }

        return $this->render('AppBundle:Book:find.html.twig', array(
            'book' => $book,
            'form' => $form->createView(),
        ));

    }

    /**
     * @Route("/step2")
     */
    public function getcarsAction()
    {

        // здесь нужно получить данные с первого шага findAction
        // например записать данные в переменную $getTrips

        $getTrips = $step1; // как в $step1 получить данные - в этом суть вопроса

        if ($form->isSubmitted() && $form->isValid()) {

            return $this->redirectToRoute('/step3');
        }

        return $this->render('AppBundle:Book:cars.html.twig', array(
            'triplist' => $getTrips,
        ));
    }

    /**
     * @Route("/step3")
     */
    public function bookAction()
    {

    }

}
 

WMix

герр M:)ller
Партнер клуба
в табличку писать нет желания или в чем вопрос?
 

alexmixaylov

Новичок
в табличку писать нет желания :)
в табличку запишется информация, если человек дойдет до конца формы
ему присвоится уникальный номер и тп

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

Kotofey

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

alexmixaylov

Новичок
о мил человек, как раз сейчас пытаюсь это сделать
PHP:
public function findAction(Request $request)
    {
        $book = new Book();
        //шаг первый - запоняем начальные поля
        $form = $this->createFormBuilder($book)
            ->add('date', DateTimeType::class, array('widget' => 'single_text'))
            ->add('fromBook', ChoiceType::class)
            ->add('toBook', ChoiceType::class)
            ->getForm();

        $form->handleRequest($request);

        if ($form->isSubmitted()) {

            // как правильно получить данные из формы? так?
            // или просто $form использовать
             $data = $form->getData();

            return $this->redirectToRoute('app_book_getcars', array(
                'form'=> $data
     // или  'form'=> $form
            ));

        }
    }
а теперь пытаюсь передать это во второй екшн
PHP:
    /**
     * @Route("/step2")
     */
    public function getcarsAction(Request $request)
    {

        $getTrips = $request;

        return $this->render('AppBundle:Home:index.html.twig', array(
         'getTrips'    => $getTrips
        ));
    }
делаю дамп $request - там данных нет, но смущает меня что метод GET а я передаю ПОСТ
Request {#8 ▼
+attributes: ParameterBag {#11 ▶}
+request: ParameterBag {#9 ▶}
+query: ParameterBag {#10 ▼
#parameters: []
}
+server: ServerBag {#14 ▶}
+files: FileBag {#13 ▶}
+cookies: ParameterBag {#12 ▼
#parameters: array:1 [▼
"PHPSESSID" => "5hij1pqbl6puh40djhg2lnbvb0"
]
}
+headers: HeaderBag {#15 ▶}
#content: null
#languages: null
#charsets: null
#encodings: null
#acceptableContentTypes: null
#pathInfo: "/step2"
#requestUri: "/step2"
#baseUrl: ""
#basePath: ""
#method: "GET"
#format: null
#session: Session {#160 ▶}
#locale: null
#defaultLocale: "en"
}
 

WMix

герр M:)ller
Партнер клуба
в табличку писать нет желания :)
в табличку запишется информация, если человек дойдет до конца формы
ему присвоится уникальный номер и тп

вопрос в том что только начал учить симфони и многие вещи пока не получается сделать
например, по логике нужно записать данные формы из первого шага в сессию
и на вторм шаге вытянуть это дело отуда
но как в контролере сделать это, не пойму
а зачем это тебе? почему бы в сессию просто не записать "уникальный номер" и по мере поступления данных обновлять табличку?
 
  • Like
Реакции: AmdY

alexmixaylov

Новичок
почему бы в сессию просто не записать "уникальный номер" и по мере поступления данных обновлять табличку?
тогда будет база расти, зашел человек, глянул цены и ушел :), а строка в таблице уже создана

если только не настроить какое то автоудаление неполных строк

там выше человек написал что из одного екшна в другой можно передать
пробую так сделать, делаю дамп $request - там данных нет
 

WMix

герр M:)ller
Партнер клуба
ну и пусть себе растет, будет что анализировать, удалить то все одним запросом.
не можешь автоматизировать ручками удаляй
 

alexmixaylov

Новичок
может вы и правы
а как можно записать уникальный номер для того чтоб потм в следуюшем екшене вытащить запись по нему?
 

alexmixaylov

Новичок
пробую добавить в контроллер
PHP:
        //шаг первый - запоняем начальные поля
        $form = $this->createFormBuilder($book)
            ->add('sessid', 'hidden', array('attr' => array('value' => $request->cookies->get('PHPSESSID'))))
            ->add('date', DateTimeType::class, array('widget' => 'single_text'))
            ->add('fromBook', ChoiceType::class)
            ->add('toBook', ChoiceType::class)
            ->add('returnDate', DateTimeType::class, array('widget' => 'single_text'))
            ->add('returnFrom', ChoiceType::class)
            ->add('returnTo', ChoiceType::class)
            ->add('people')
            ->add('isReturn', CheckboxType::class)
            ->getForm();
здесь баг получается, чтобы получить PHPSESSID нужно перезагрузить страничку
и чтобы в базу записать уникальный идентификатор
нужно вначале перезагрузить страницу
 

WMix

герр M:)ller
Партнер клуба
Зачем тебе пхпсессид? (Она по идеи есть перегружать ничего не нужно), но просто записываешь в табличку, получаешь ид-записи, эту ид записываешь в сессию
 

Вурдалак

Продвинутый новичок
Такие вещи вообще нужно делать на клиенте. И хранение совокупности всех данных от трёх форм ляжет на клиент.
 

alexmixaylov

Новичок
PHP:
        if ($form->isSubmitted() && $form->isValid()) {

            $em = $this->getDoctrine()->getManager();
            $em->persist($book);
            $em->flush();

// записал в базу как получить ID этой записи? например $bookid
// как записать это дело в сессию?

// если делаю так, то ругается что сессия уже запущена
$session = new Session();
$session->start();
$session->set('bookid', $bookid);

            return $this->redirectToRoute('app_book_getcars', array(
                'data'=> $data,
                'form' => $form
            ));

        }
 

artoodetoo

великий и ужасный
@alexmixaylov, как тебе такой вариант:
  • делаешь одну большую форму с полным набором полей. "шаги" выделяешь в ней с помощью <fieldset>. экшн для сохранения один! никакой особой логики для частично сохраненной записи, никаких лишних сущностей.
  • на стороне клиента режешь форму на отдельные части по филдсетам, добавляешь кнопки взад-вперед.
  • в каждый момент времени показывается только один филдсет
  • профит
Собственно к Симфони решение не имеет отношения, оно универсальное. Концептуально правильное, т.к. "многошаговый мастер" это очевидно элемент Представления, мы не затрагиваем другие слои.

https://github.com/artoodetoo/formToWizard
 
Последнее редактирование:

Kotofey

FloodMaster.
@alexmixaylov, как тебе такой вариант:
  • делаешь одну большую форму с полным набором полей. "шаги" выделяешь в ней с помощью <fieldset>. экшн для сохранения один! никакой особой логики для частично сохраненной записи, никаких лишних сущностей.
  • на стороне клиента режешь форму на отдельные части по филдсетам, добавляешь кнопки взад-вперед.
  • в каждый момент времени показывается только один филдсет
  • профит
Собственно к Симфони решение не имеет отношения, оно универсальное. Концептуально правильное, т.к. "многошаговый мастер" это очевидно элемент Представления, мы не затрагиваем другие слои.

https://github.com/artoodetoo/formToWizard
А если логика следующего шага зависит от первой формы, как тогда с этим подходом решишь, тоже всё на клиент?)
 

Вурдалак

Продвинутый новичок
А если логика следующего шага зависит от первой формы, как тогда с этим подходом решишь, тоже всё на клиент?)
Серверу пофиг на формы, его интересуют бизнес-действия. Всё будет то же самое, просто после выполнения первого бизнес-действия (регистрация, например), клиент дорисует, что нужно (к примеру, форму заказа).
 
Сверху