Drupal → Как в #ajax callback сгенерировать новую форму чтобы ей не мешали GET и POST данные текущего запроса

14.09.2022

Если попытаться в #ajax callback сгенерировать новую форму, то она подхватит данные из текущего запроса и скорей всего попытается снова засабмититься, уйдя в бесконечный цикл. Чтобы этого не происходило надо создать временный объект Request, поместить его в стэк, сгенерировать форму и удалить Request из стэка. В простейшем случае это выглядит так:

$fake_request = new \Symfony\Component\HttpFoundation\Request();
\Drupal::requestStack()->push($fake_request);
... generate form ...
\Drupal::requestStack()->pop();

Более сложный пример генерации формы добавления товара в корзину:

$request_stack = \Drupal::requestStack();
$product_id = 123;

// Create fake request object to product page
$url = Url::fromRoute('entity.commerce_product.canonical', ['commerce_product' => $product_id]);
$fake_request = Request::create($url->toString());
$fake_request->attributes->add([
  RouteObjectInterface::ROUTE_NAME => $url->getRouteName(),
  RouteObjectInterface::ROUTE_OBJECT => \Drupal::service('router.route_provider')->getRouteByName($url->getRouteName()),
  '_raw_variables' => new ParameterBag(['commerce_product' => $product_id]),
  'commerce_product' => Product::load($product_id),
]);

// Push fake request to requests stack
$request_stack->push($fake_request);

// Build "add to cart" form (form builder will use fake request from stack)
$form_build = \Drupal::service('commerce_product.lazy_builders')->addToCartForm($product_id, 'full', TRUE, 'ru');

// Remove fake request from requests stack
$request_stack->pop();

Способ с созданием собственного Request объекта и помещения его в стэк очень часто используется при написании тестов.

Написанное актуально для
Drupal 9+
Похожие записи

Добавить комментарий