Drupal 7 页面传递回调
或者,如何使用完全不同的模板呈现 Drupal 页面。
我最近有一个需求,我需要让 Drupal 呈现一个与网站的正常页面布局完全分开的 HTML 页面。这实际上是 API 回调的一部分,但这让我参与了研究 Drupal 7 中传递回调的工作方式。没有必要仅仅为了渲染带有一些自定义 HTML 的单个页面的工作而创建一个新主题,尤其是因为 Drupal 有提供这种内置的机制。
如果您做过很多 Drupal 编程,您可能已经使用了传递回调,但实际上并没有意识到它。调用函数喜欢drupal_access_denied()和drupal_not_found()会分别发出403或404页,但他们通过烧成页面,这使得交付回调的工作,然后发送页面输出到浏览器。这些函数通过调用函数来工作,drupal_deliver_page()函数又会触发当前选择的传递回调函数被调用。默认情况下, this is drupal_deliver_html_page(),它使用当前主题呈现 HTML 输出,添加适当的标题,并将此内容发送到浏览器。
有两种方法可以更改传递回调,使用哪一种取决于您的需要。
实施 hook_page_delivery_callback_alter()
就在drupal_deliver_page()finally 调用之前drupal_deliver_html_page(),安装的模块有机会通过hook_page_delivery_callback_alter()钩子改变传递回调。这个钩子允许你根据某些参数改变传递回调函数。下面显示了用于更改站点首页的传递回调函数的钩子。稍后我们将介绍自定义交付功能的内容。
/*** Implements hook_page_delivery_callback_alter().
*/
function mymodule_page_delivery_callback_alter(&$delivery_callback) {
if (drupal_is_front_page()) {
$delivery_callback = 'mymodule_deliver_page';
}
}
这个钩子不仅可以用来改变页面模板。因为它是在页面回调运行之后调用的,但在页面(以及大部分,如果不是全部内容)呈现之前,它是在页面呈现之前更改某些内容的好方法。例如,我发现这个钩子是改变页面菜单位置的好方法。以以下愚蠢的示例为例,这会移动 Cron 设置页面,使其看起来位于模块页面下方。
/*** Implements hook_page_delivery_callback_alter().
*/
function mymodule_page_delivery_callback_alter(&$delivery_callback) {
if (implode(arg(), '/') == 'admin/config/system/cron') {
menu_tree_set_path('management', 'admin/modules');
}
}
这本身并没有用,但是让某些页面出现在某些菜单项下是难以正确解决的常见 Drupal 问题之一。这个钩子提供了一个很好的方法来做到这一点。
菜单传递回调
提供自定义回调的第二种方法是使用菜单挂钩项的传递回调属性。此选项意味着菜单回调的输出将自动传递到此传递回调,而无需定义任何挂钩。以下示例在菜单挂钩和非常简单的页面回调函数中显示了这一点。
function mymodule_menu() {$items['mymodule/page'] = array(
'title' => 'A Page',
'page callback' => 'mymodule_return',
'access callback' => TRUE,
'delivery callback' => 'mymodule_deliver_page',
'type' => MENU_CALLBACK,
);
return $items;
}
function mymodule_return() {
return '<p>' . t('The current timestamp is') . ' : ' . time().'</p>';
}
这个菜单页面回调不需要做任何特别的事情,但它产生的所有内容都被馈送到传递回调函数。页面回调函数也不需要有什么特别之处,它可以像往常一样返回一个字符串或一个 Drupal 渲染数组。在当前状态下,上面的代码将产生一个白屏,并且在看门狗表中将看到错误消息“callback mymodule_deliver_page not found: mymodule/page”。这是因为缺少deliver 回调函数,所以我们来看看创建一个。
创建交付回调函数
为了使上述代码示例正常工作,您需要创建一个传递回调函数。用最简单的术语来说,传递回调函数必须简单地打印出页面的内容。下面虽然简单,但满足了这个要求。
function mymodule_deliver_page($page_callback_result) {print render($page_callback_result);
}
有了这个,上面的代码示例现在可以工作了。尽管页面将是空白的,因为这仅提供内容,而没有其他 HTML 或样式。
在创建您自己的传递回调之前,了解 Drupal 在这方面的工作方式很重要。Drupal 7 中 HTML 页面的传递回调函数被调用drupal_deliver_html_page(). 这个函数在这里重现有点太长了,但是它通过适应 Drupal 在页面渲染过程中返回的不同类型的变量来工作。如果页面回调返回一个整数,则该函数会将其视为错误,并将使用错误代码返回该错误的正确标题和页面。这是一个有用的效果,因为它意味着要生成访问被拒绝的页面,您只需要从页面回调中返回 MENU_ACCESS_DENIED 常量。MENU_ACCESS_DENIED 是一个整数常量,这意味着 Drupal 将返回 403 HTTP 状态代码和访问被拒绝页面。如果页面回调返回一个字符串或数组,则将其传递给drupal_render_page()函数,该函数将正常呈现页面。
我们可以将drupal_deliver_html_page()功能减少到最基本的要求,并在单个模板中呈现我们的页面内容。下面将在一个简单的 HTML 结构中呈现页面内容之前发出几个标题。最后的drupal_page_footer()函数是一个 Drupal 实用程序函数,它编写会话并调用任何关闭函数,这些函数应该始终在页面末尾调用。
function mymodule_deliver_page($page_callback_result) {if (is_null(drupal_get_http_header('Content-Type'))) {
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
}
// 为浏览器和搜索引擎发送适当的 HTTP 标头。
global $language;
drupal_add_http_header('Content-Language', $language->language);
// 呈现页面和内容
print '<html><head></head><body>';
print render($page_callback_result);
print '</body></html>';
drupal_page_footer();
}
为了使其更易于维护,您显然会将其包装在主题函数中,但此示例作为一个简单示例工作。我使用了上述代码的一个版本(通过模板文件传递输出)来生成 API 回调所需的输出。这里的结果是,如果输出由于某种原因需要更改,那么所有需要更改的就是模板文件,其他所有内容都由模块处理。
还要记住,我们在这里基本上绕过了 Drupal 访问被拒绝的逻辑,因此您需要非常确保您返回的输出是合适的。如果您使用hook_page_delivery_callback_alter()钩子来改变页面交付,这一点尤其重要。您可以很容易地打开未发布的内容或用户个人资料的详细信息,以便匿名查看,所以要小心!
返回 JSON 输出
也许对传递回调最有用的事情是以不同的格式返回输出。这可以通过稍微调整mymodule_deliver_page()函数来轻松完成,以便它侦听不同类型的标题,为遇到的每种 mime 类型稍微调整输出。
<?phpfunction mymodule_deliver_page($page_callback_result) {
$content_type = drupal_get_http_header('Content-Type');
if (is_null($content_type)) {
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
}
// 为浏览器和搜索引擎发送适当的 HTTP 标头。
global $language;
drupal_add_http_header('Content-Language', $language->language);
switch ($content_type) {
case 'application/json':
print json_encode($page_callback_result);
break;
case 'application/xml':
print '<?xml version="1.0" encoding="UTF-8"><root>' . render($page_callback_result) . '</root>';
break;
default:
print '<html><head></head><body>';
print render($page_callback_result);
print '</body></html>';
}
drupal_page_footer();
}
为了生成 JSON 输出,我们现在需要做的就是确保页面回调设置一个“application/json”标头。
function mymodule_return() {drupal_add_http_header('Content-Type', 'application/json');
return array(t('The current timestamp is') . ' : ' . time());
}
这将生成以下输出。
["The current timestamp is : 1440147347"]
我们还可以通过一些简单的更改切换到 XML 输出。
function mymodule_return() {drupal_add_http_header('Content-Type', 'application/xml');
return t('The current timestamp is') . ' : ' . time();
}
这使得在 Drupal 中生成简单的 API 服务变得非常容易。Drupal 假定您的内容将是 HTML,但是通过几行代码,您可以让 Drupal 以您喜欢的任何格式返回内容。
以上是 Drupal 7 页面传递回调 的全部内容, 来源链接: utcz.com/z/317332.html