it-swarm-es.com

hook_preprocess_page: "node_load () + node_page_view ()" versus "% node + node_page_view ()"

Existe un nodo básico (nid "123") y un módulo registró dos rutas usando hook_menu:

  • first/%node
  • second

Ambas devoluciones de llamada de página usan node_page_view($node) para mostrar una vista de página completa del nodo, excepto que la segunda devolución de llamada usa adicionalmente node_load(123) para obtener una referencia a $node.

Por lo tanto, http://localhost/first/123 Y http://localhost/second Tienen el mismo aspecto en lo que respecta al usuario.


Sin embargo, hook_preprocess_page Recibe la variable node solo con la primera ruta, por lo tanto Drupal obviamente hace algo más allá de node_load Cuando ve un comodín %node, ¿Alguna idea de qué es para que hook_preprocess_page reciba la referencia a $node en ambos casos? (porque manejar todo internamente en la segunda ruta produce URL mucho más amigables que redirigir a la primera ruta desde la segunda).

Ejemplo:

<?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);
}

(Fuente del archivo mymodule.module)


Mi mejor/única esperanza hasta ahora es profundizar en la fuente de node_page_view Y todas las funciones que consecuentemente activa hasta encontrar lo que sucede entre el momento en que se llama node_page_view Y el momento en que se llama module_invoke_all que desencadena el gancho se llama.

2
wildpeaks

Cuando se invoca mymodule_preprocess_page() para la ruta "primer /% nodo", obtiene el objeto de nodo porque la ruta está asociada con un nodo del módulo.
Drupal no puede asociar un objeto de nodo con una ruta como "/ admin/content/node" (ruta de Drupal 6) porque la ruta no contiene ninguna referencia a una ID de nodo que esté marcada como ID de nodo. ¿Qué objeto de nodo debería Drupal devolver para tales rutas, considerando un Drupal sitio web puede contener cientos de nodos?

Su pregunta es "¿cómo puede Drupal asociar un objeto de nodo en un caso, pero no en el otro?"

La respuesta está en el código template_preprocess_page () , que la función ejecutó antes de que se procese la plantilla page.tpl.php.
En esa función, encontrará el siguiente código:

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

Los parámetros predeterminados para menu_get_object () son $type = 'node', $position = 1, $path = NULL, Lo que significa que template_preprocess_page() solicita el objeto de nodo que está asociado con el marcador de posición en la posición # 1, que es el valor devuelto, por ejemplo, de arg(1).

Si observa la fuente de menu_get_object(), notará que el código que se está ejecutando es el siguiente:

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];
  }
}

Usando los argumentos predeterminados, la función verificará que la función de carga asociada con el elemento de ruta # 1 es node_load(). Si la función de carga es esa, entonces devolverá el valor devuelto por la función de carga a la función de llamada (en nuestro caso, template_preprocess_node()).

Para obtener automáticamente un objeto de nodo, su devolución de llamada de menú debe usar una ruta como "segundo /% nodo" (que sería compatible con los argumentos menu_get_object() predeterminados). El único problema es que para tales rutas es necesario pasar el ID de nodo; si la URL es http://example.com/second , Drupal mostrará una página de error 404, ya que el marcador de posición requiere un parámetro que debe pasarse.
Para resolver este problema, el módulo debe definir dos devoluciones de llamada de menú: una asociada con "segundo" y otra asociada con "segundo /% nodo". La primera devolución de llamada del menú no obtendría un objeto de nodo, mientras que la segunda obtendría el objeto de nodo (y mymodule_preprocess_page() también lo obtendría).

Como alternativa, debe cambiar el código de mymodule_preprocess_page() a algo similar a:

/**
 * 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
kiamlaluno

Cuando Drupal ve el comodín '% node' en la URL, sabe que el argumento hace referencia a un ID de nodo, por lo que establece automáticamente el $node variable para usted, haciéndola disponible en hook_preprocess_page. En su "segundo" menú de devolución de llamada, debe configurar el $vars['node'] variable. De esa manera puedes usarlo hook_preprocess_page.

Referencia: http://drupal.org/node/22417

1
Chaulky