Рейтинг:0

hook_forms() не работает

флаг br

Я пытаюсь добавить кнопку во все формы узлов с помощью обратного вызова в hook_forms. Я получаю аналогичную ошибку. Может кто-нибудь помочь.

Предупреждение: call_user_func_array() ожидает, что параметр 1 будет допустимым обратным вызовом, класс 'my_dossier_form' не найден в drupal_retrieve_form() (строка 844 файла /var/www/includes/form.inc).
Примечание: Преобразование массива в строку в drupal_prepare_form() (строка 1094 файла /var/www/includes/form.inc).
Примечание: Преобразование массива в строку в drupal_prepare_form() (строка 1108 файла /var/www/includes/form.inc).
Примечание: Преобразование массива в строку в drupal_prepare_form() (строка 1128 файла /var/www/includes/form.inc).

Код

функция my_dossier_forms($form_id, $args) {
  $ формы = массив();
  если ($types = node_type_get_types()) {
    foreach (array_keys($types) как $type) {
      $формы[$тип . '_node_form']['callback'] = 'my_dossier_form';
    }
  }

  вернуть $ формы;
}

функция my_dossier_form($form, &$form_state) {
  $ форма ['удалить'] = массив (
    '#type' => 'отправить',
    '#значение' => т('Удалить'),
    '#вес' => 10,
  );
  вернуть $ форму;
}
beltouche avatar
флаг cn
Вы уверены, что вам не нужен `hook_form_alter`?
Павел Герасюта avatar
флаг br
По задаче мне нужно использовать hook_forms конкретно.
Jaypan avatar
флаг de
Ваш код выглядит нормально, но он не находит `my_dossier_form()`. В каком файле эта функция? Возможно, вам потребуется явно включить его.
Павел Герасюта avatar
флаг br
В файле my_dossier.module.
Павел Герасюта avatar
флаг br
Я думал об использовании module_load_include
apaderno avatar
флаг us
@beltouche Я согласен. Конструктор форм, установленный с помощью `hook_forms()` (также известный как значение *callback*), должен создавать полную форму, а не только кнопку отправки. Кажется, что задача ОП заключается в изменении форм редактирования узла, для которых `hook_form_BASE_FORM_ID()` является хуком для реализации.
Рейтинг:1
флаг us

Какие node_type_get_types() возвращает ассоциативный массив объектов типа узла, с ключом по типу. Описание возвращаемого значения более понятно в _node_types_build() документация.

Реализация хука, выполненная, например, из основного модуля Drupal comment_forms(), помогает понять правильный код.

функция comment_forms() {
  $ формы = массив();
  foreach (node_type_get_types() как $type) {
    $forms["comment_node_{$type->type}_form"]['callback'] = 'comment_form';
  }
  вернуть $ формы;
}

В вашем случае код должен быть похож на следующий.

функция my_dossier_forms($form_id, $args) {
  $ формы = массив();
  foreach (node_type_get_types() как $type) {
    $forms["my_dossier_node_{$type->type}_form"]['callback'] = 'my_dossier_form';
  }

  вернуть $ формы;
}

Этот код не сильно отличается от кода, показанного в вопросе, и сам по себе он не вызовет класс 'my_dossier_form' не найден ошибка.

строка 844 является следующим.

$form = call_user_func_array(isset($callback) ? $callback: $form_id, $args);

$обратный вызов инициализируется из следующего кода.

если (!isset($forms) || !isset($forms[$form_id])) {
  $forms = module_invoke_all('forms', $form_id, $args);
}
$form_definition = $forms[$form_id];
if (isset($form_definition['аргументы обратного вызова'])) {
  $args = array_merge($form_definition['аргументы обратного вызова'], $args);
}
если (isset($form_definition['обратный вызов'])) {
  $callback = $form_definition['обратный вызов'];
  $form_state['build_info']['base_form_id'] = isset($form_definition['base_form_id']) ? $form_definition['base_form_id'] : $обратный вызов;
}

Строка 844 не могла думать my_dossier_form является классом, за исключением случая $обратный вызов содержит массив, подобный массив('my_dossier_form', 'mymodule_form');, либо он содержит строку типа 'my_dossier_form::имя_метода'.

Предупреждения о преобразовании массива в строку означают, что Drupal получает массив, когда ожидает строку, например, из следующей строки (строка 1094).

    elseif (isset($form_state['build_info']['base_form_id']) && function_exists($form_state['build_info']['base_form_id']. '_validate')) {

Я бы просто не возвращал идентификатор формы, начинающийся с $тип поскольку это, вероятно, создает конфликты с другими модулями, реализующими крюк_формы(), каждый из которых должен возвращать уникальный идентификатор формы. Видеть module_invoke_all() понять, что происходит, когда двое крюк_формы() реализации возвращают информацию для одного и того же идентификатора формы.

  foreach (module_implements($hook) как $module) {
    $функция = $модуль. '_' . $ крючок;
    если (функция_существует($функция)) {
      $result = call_user_func_array($function, $args);

      // В случае hook_forms() $result содержит массив.
      если (isset($result) && is_array($result)) {
        $ return = array_merge_recursive ($ return, $ результат);
      }

      elseif (isset($результат)) {
        $возврат[] = $результат;
      }
    }
  }

Точнее, два модуля, возвращающие значения для одного и того же идентификатора формы, могли как минимум вызвать call_user_func_array() ожидает, что параметр 1 будет допустимым обратным вызовом, класс '[callback]' не найден когда они оба устанавливают значение для одного и того же обратного вызова. Посмотрите вывод следующего кода, чтобы понять, что именно происходит.

$return["type_node_form"]["обратный вызов"] = "my_dossier_form";
$result["type_node_form"]["обратный вызов"] = "mymodule_form";
print_r(array_merge_recursive($return, $result));

перезвонить value становится массивом из двух строк, которые call_user_func_array() интерпретируется как массив, содержащий имя класса и имя метода.

Множество
(
    [type_node_form] => Массив
        (
            [обратный вызов] => Массив
                (
                    [0] => my_dossier_form
                    [1] => mymodule_form
                )

        )

)

В данном случае конфликт возникает с модулем Node, который использует следующий код для это крюк_формы() выполнение.

функция node_forms() {
  $ формы = массив();
  если ($types = node_type_get_types()) {
    foreach (array_keys($types) как $type) {
      $формы[$тип . '_node_form']['обратный вызов'] = 'node_form';
    }
  }
  вернуть $ формы;

В качестве примечания, крюк_формы() целью является предоставление одного и того же построителя форм для группы форм, идентификаторы которых соответствуют схеме, например, в случае форм редактирования комментариев, идентификаторы которых comment_node_[тип узла]_form. При наличии обратный вызов конструктора форм (передается как перезвонить value) должен строить полную форму, а не ее часть.
Факт my_dossier_form() создает только кнопку отправки, и my_dossier_forms() использует тот же код, что и node_forms() заставляет меня думать, что целью кода является изменение форм редактирования узла, что должно быть достигнуто путем реализации hook_form_BASE_FORM_ID_alter(). Вот что делает модуль Book с book_form_node_form_alter(), который вызывается для формы редактирования узла каждого типа контента.

function book_form_node_form_alter(&$form, &$form_state, $form_id) {
  $узел = $форма['#узел'];
  $access = user_access('управление структурой книги');
  если (!$доступ) {
    if (user_access('добавить содержимое в книги') && (!empty($node->book['mlid']) && !empty($node->nid) || book_type_is_allowed($node->type))) {

      // Уже в книжной иерархии, или этот тип узла разрешен.
      $доступ = ИСТИНА;
    }
  }
  если ($ доступ) {
    _book_add_form_elements($form, $form_state, $node);

    // Так как раскрывающийся список "Книга" не может инициировать отправку формы, когда
    // JavaScript отключен, для этого добавьте кнопку отправки. book.css скрывает
    // эта кнопка, когда включен JavaScript.
    $form['книга']['книга выбора'] = массив(
      '#type' => 'отправить',
      '#value' => t('Изменить книгу (обновить список родителей)'),
      '#submit' => массив(
        'book_pick_book_nojs_submit',
      ),
      '#вес' => 20,
    );
  }
}

Если хуку нужно использовать имя типа контента, доступное в $form['#узел']->тип.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.