hook_preprocess_page:“ node_load() + node_page_view()” vers "%node + node_page_view()”
質問
基本ノード(nid "123")が存在し、モジュールが2つのパスを登録しました hook_menu
:
first/%node
second
両方のページコールバックが使用されます node_page_view($node)
ノードのフルページビューを表示するには、2番目のコールバックが追加で使用されることを除きます node_load(123)
参照を取得します $node
.
したがって http://localhost/first/123
と http://localhost/second
ユーザーに関する限り、同じように見えます。
でも hook_preprocess_page
受信します node
したがって、最初のパスでのみ変数があります Drupalは明らかにそれを超えて何かをします node_load
それが見えるとき %node
ワイルドカード、それが何であるか考えています hook_preprocess_page
への参照を受信します $node
両方の場合において ? (2番目のパスですべてを内部的に処理すると、2番目のパスから最初のパスにリダイレクトするよりもはるかに友好的な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
フックが呼び出されます。
解決
いつ mymodule_preprocess_page()
「First/%ノード」パスに呼び出されると、パスがモジュールからのノードに関連付けられているため、ノードオブジェクトが取得されます。
Drupalは、ノードIDとしてマークされたノードIDへの参照が含まれていないため、「/admin/content/node」(Drupal 6 Path)などのパスにノードオブジェクトを関連付けることはできません。 Drupal Webサイトには数百のノードが含まれることを考慮して、そのようなパスにDrupalを返す必要があるノードオブジェクトはどれですか?
あなたの質問は、「Drupalは1つのケースでどのようにノードオブジェクトを関連付けることができますか?
答えはにあります 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()
).
ノードオブジェクトを自動的に取得するには、メニューコールバックは「second/%node」などのパスを使用する必要があります(これはデフォルトと互換性があります menu_get_object()
引数)。唯一の問題は、そのようなパスの場合、ノードIDを渡す必要があることです。 URLの場合 http://example.com/second, 、Drupalには404エラーページが表示されます。プレースホルダーには、渡す必要があるパラメーターが必要です。
この問題を解決するには、モジュールは2つのメニューコールバックを定義する必要があります。1つは「2番目」に関連付けられ、もう1つは「2番目/%ノード」に関連付けられています。最初のメニューコールバックはノードオブジェクトを取得しませんが、2番目はノードオブジェクトを取得します(そして 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();
}
// …
}
}
他のヒント
DrupalがURLで「%ノード」ワイルドカードを見ると、引数がノードIDを参照していることがわかっているため、自動的に設定されます $node
あなたのために変数、それを利用可能にします hook_preprocess_page
. 。 「2番目の」メニューコールバックで、 $vars['node']
変数。そうすれば、それを使用できます hook_preprocess_page
.