Drupal 8-9: Как передать данные формы в другое место сайта?

Главные вкладки

Аватар пользователя nick80 nick80 12 апреля 2023 в 17:30

Всем добрый день.
Сайт на последней версии Durpal 9.
Задача простая, но не могу найти решение ее для Drupal - передать данные формы в другое место сайта.
Форма создана с помощью кастомного модуля на form api - расчет стоимости доставки через API Почта РФ.
В форме одно текстовое поле и кнопка submit.
Функция submitForm получает данные с формы

<?php
$address 
$form_state->getValue('delivery_address');
?>

Далее идет отправка адреса из формы по API почта РФ и получение от туда стоимости доставки.
Стоимость записываю в переменную

<?php
@$_POST['total_price'] = $total_price;
 
?>

И далее в файле my_theme.theme через preprocess_block пытаюсь там получить эту переменную. В этом блоке будет выводиться этот результат стоимости доставки.

<?php
function theme_preprocess_block__apipost(&$variables) {
kint($_POST);
}
?>

В массиве ничего нет.
Подскажите как передавать переменные из формы в другое место? может через конфигурации? сохранять данные в submitForm в конфигурацию? Есть какой-то стандартный общепринятый способ?
Везде в примерах в интернете полученные данные с формы выводят в статус и никуда не передают.

<?php
\Drupal::messenger()->addStatus(@$_POST['total_price']);
?>

Может их как-то можно передать в контроллер кастомного модуля с формой?
Контроллер модуля формирует вывод формы

<?php
class ApiRussianPost extends BlockBase {
  
/**
   * {@inheritdoc}
   */
  
public function build() {

    

$form = \Drupal::formBuilder()->getForm('Drupal\pochta\Form\DeliveryForm');
    return 
$form;

  }
}

?>

Комментарии

Аватар пользователя OldWarrior OldWarrior 16 апреля 2023 в 23:45

nick80 wrote: передать данные формы в другое место сайта

Как ни крутил вопрос - так и не понял, почему это "другое место". Форма загружается из блока. Но ведь в блоке вам нужен и результат.

Тогда в вашей сабмит-функции можно так:

<?php
...
$address $form_state->getValue('delivery_address');
...
$total_price =  ...; // Результат ваших вызовов API и т.д.
// Записываем значение в $form_state.
$form_state->set('total_price'$total_price);
// В зависимости от механики формы или наличия AJAX'а ещё может 
// потребоваться в сабмит-функции добавление вызова $form_state->setRebuild().
$form_state->setRebuild();
...
?>

А в вашем билдере формы тогда можно так:

<?php
  
...
  public function 
build() {
  
$form = \Drupal::formBuilder()->getForm('Drupal\pochta\Form\DeliveryForm');
    if (
$total_price $form_state->get('total_price')) {
      
// Выведется как обычный маркап ниже всей формы.
      
$form['total_price'] = [
        
'#markup' => 'Total price: ' $total_price
      
];
    }
    return 
$form;
  }
  ...
?>
Аватар пользователя OldWarrior OldWarrior 17 апреля 2023 в 0:07

PS. Проскочил, у вас же это не build-функция формы, значит $form_state в явном виде недоступен.

Тогда этот блок кода можно поместить в build-функцию формы:

<?php
    
...
    if (
$total_price $form_state->get('total_price')) {
      
// Выведется как обычный маркап ниже всей формы.
      
$form['total_price'] = [
        
'#markup' => 'Total price: ' $total_price
      
];
    }
    ...
?>
Аватар пользователя nick80 nick80 20 апреля 2023 в 17:13

Спасибо за ответ. Указанный Вами способ работает, но для вывода информации в рядом с формой (в том же блоке).
Нашел для себя вот такое решение https://niklan.net/blog/74
Это работает как мне надо, но появилась новая проблема, значение в форме не сбрасывается после function submitForm. То есть если зайти на другую страницу и вернуться опять на ту где расположена форма, то значения уставлены, которые пользователь вводил последний раз. Более того, даже если закрыть браузер, открыть его заново в инкогнито, все равно в $form_state хранятся данные предыдущего ввода.
В конец функции submitForm вставляю

<?php
$form_state
->unsetValue('delivery_address');
?>

Смотри рисунок