страница предварительной обработки крючка: "загрузка узла() + просмотр страницы узла()" по сравнению с "%узел + просмотр страницы узла()"


Существует базовый узел (nid "123"), и модуль зарегистрировал два пути, используя hook_menu:

  • first/%node
  • second

Оба обратных вызова страницы используют node_page_view($node) для отображения полностраничного представления узла, за исключением того, что второй обратный вызов дополнительно использует node_load(123) для получения ссылки на $node.

Поэтому http://localhost/first/123 и http://localhost/second выглядят одинаково, насколько это касается пользователя.


Однако hook_preprocess_page получает переменную node только с первый путь, поэтому Drupal, очевидно, делает что-то помимо node_load, когда он видит подстановочный знак %node, любая идея, что это такое, чтобы hook_preprocess_page получал ссылку на $node в обоих случаях ? (потому что внутренняя обработка всего во втором пути создает гораздо более удобные URL-адреса, чем перенаправление на первый путь со второго).

Пример:

<?php

/**
 * Implementation of hook_preprocess_page().
 */
function mymodule_preprocess_page(&$vars){
    if (@isset($vars['node'])) echo '<h1>[mymodule.module] Node is defined</h1>';
    else echo '<h1>[mymodule.module] Node is NOT defined</h1>';
}


/**
 * Implementation of hook_menu().
 */
function mymodule_menu(){
    return array(
        'first/%node' => array(
            'title' => 'First callback',
            'page callback' => 'mymodule_page_first',
            'page arguments' => array(1),
            'access callback' => TRUE, 
        ),
        'second' => array(
            'title' => 'Second callback',
            'page callback' => 'mymodule_page_second',
            'access callback' => TRUE, 
        ),
    );
}

/**
 * Page callback for url "http://localhost/first/123".
 */
function mymodule_page_first($node){
    echo '<h1>[mymodule.module] Function mymodule_page_first</h1><pre>';
    var_dump($node);
    echo '</pre>';

    return node_page_view($node);
}


/**
 * Page callback for url "http://localhost/second".
 */
function mymodule_page_second(){
    $node = node_load(123); //the ID of an existing node

    echo '<h1>[mymodule.module] Function mymodule_page_second</h1><pre>';
    var_dump($node);
    echo '</pre>';

    return node_page_view($node);
}

(Источник файла mymodule.module)


Моя лучшая/единственная надежда на данный момент - это покопаться в источнике node_page_view и все функции, которые он, следовательно, запускает, пока я не найду, что происходит между моментом вызова node_page_view и моментом вызова module_invoke_all, который запускает крючок.

Author: wildpeaks, 2011-03-15

2 answers

Когда mymodule_preprocess_page() вызывается для пути "первый/%узел", он получает объект узла, потому что путь связан с узлом из модуля.
Drupal не может связать объект узла с путем, таким как "/admin/содержимое/узел" (путь Drupal 6), потому что путь не содержит ссылки на идентификатор узла, который помечен как идентификатор узла. Какой объект узла должен возвращать Drupal для таких путей, учитывая, что веб-сайт Drupal может содержать сотни узлов?

Ваш вопрос: "как может Drupal связать объект узла в одном случае, но не в другом?"

Ответ содержится в коде template_preprocess_page(), который функция выполнила перед шаблоном page.tpl.php визуализируется.
В этой функции вы найдете следующий код:

if ($node = menu_get_object()) {
  $variables['node'] = $node;
}

Параметры по умолчанию для menu_get_object() являются $type = 'node', $position = 1, $path = NULL, что означает, что template_preprocess_page() запрашивает объект узла, связанный с заполнителем в позиции #1, который является возвращаемым значением, например, из arg(1).

Взглянув на источник menu_get_object(), вы заметите, что выполняемый код выглядит следующим образом:

function menu_get_object($type = 'node', $position = 1, $path = NULL) {
  $router_item = menu_get_item($path);
  if (isset($router_item['load_functions'][$position]) && !empty($router_item['map'][$position]) && $router_item['load_functions'][$position] == $type . '_load') {
    return $router_item['map'][$position];
  }
}

Используя аргументы по умолчанию, функция проверит, что функция загрузки, связанная с пунктом маршрута № 1, является node_load(). Если функция загрузки такова, то она вернет значение, возвращенное функцией загрузки вызывающей функции (в нашем случае, template_preprocess_node()).

Чтобы автоматически получить объект узла, ваш обратный вызов меню должен использовать путь, такой как "второй/%узел" (который был бы совместим с аргументами по умолчанию menu_get_object()). Единственная проблема заключается в том, что для таких путей необходимо передать идентификатор узла; если URL-адрес http://example.com/second , Drupal покажет страницу с ошибкой 404, так как заполнитель требует параметра, который необходимо передать.
Чтобы решить эту проблему, модуль должен определить два обратных вызова меню: один, связанный со "вторым", и один, связанный с "вторым/%узлом". При первом обратном вызове меню узел не будет получен объект, в то время как второй получит объект узла (и mymodule_preprocess_page() тоже получит его).

В качестве альтернативы вам следует изменить код mymodule_preprocess_page() на что-то похожее на:

/**
 * Implementation of hook_preprocess_page().
 */
function mymodule_preprocess_page(&$vars){
  // Check if the page being served is one of the pages handled by the module.
  if (arg(0) == 'first' || arg(0) == 'second') {
    if (isset($vars['node'])) {
      // The page is a node page.
    }
    else {
      $vars['node'] = mymodule_load_the_default_node();
    }
    // …
  }
}
 3
Author: kiamlaluno, 2011-03-15 10:52:06

Когда Drupal видит подстановочный знак "%узел" в URL-адресе, он знает, что аргумент ссылается на идентификатор узла, поэтому автоматически устанавливает для вас переменную $node, делая ее доступной в hook_preprocess_page. В вашем "втором" обратном вызове меню вы должны установить переменную $vars['node']. Таким образом, вы можете использовать его hook_preprocess_page.

Ссылка: http://drupal.org/node/224170

 1
Author: Chaulky, 2011-03-15 03:44:44