来自 WebService 的 Drupal 模块页面

Drupal module page from WebService

我正在寻找一种优雅(尽可能多)的解决方案来在 Drupal 网站中构建特定页面。

所以,我开始于:

function hook_menu() {
    $items = array();

    $items['module/articles'] = array(
        'title' => 'List of articles',
        'page callback' => 'show_article_list',
        'access arguments' => array('access content'),
        'type' => MENU_CALLBACK,
     );
    $items['module/articles/%'] = array(
        'title' => '',
        'page callback' => 'show_article_page',
        'page arguments' => array(2),
        'access arguments' => array('access content'),
        'type' => MENU_CALLBACK,
     );

    return $items;
}

第一项return我的文章列表,第二项为文章%建立一个页面(其中% 是一个简单的 id。

关键是,我使用网络服务来获取列表和每个页面。因此 页面回调 调用我的网络服务(例如 http://api/articles)并根据结果构建页面。

有效。但是,如果我想设置每个 % 页面的标题,我必须使用 title 回调,这是另一个函数。而且,我不想再次调用我的网络服务。 要清楚:http://api/articles/id,returns 标题和内容在一个结果中。所以使用两种方法让我调用这个 url 两次:一个用于标题,另一个用于内容。

有没有更好的方法来解决这个问题?

非常感谢,

最简单和最快的解决方案是在 'module/articles/%' 菜单项的页面回调中使用 drupal_set_title()。参见:https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/drupal_set_title/7

但是,使用这种方法只能解决您的特定问题。一个更通用和优雅的解决方案是拥有一个可以加载和静态缓存文章的功能。例如,假设您的模块名为 article。你首先定义一个这样的函数:

function article_load($id) {
  // The $articles is an array of article objects from the webservice.
  $articles = &drupal_static(__FUNCTION__);
  if (!isset($articles[$id])) {
    $articles[$id] = call_to_your_webservice_to_load_the_article($id);
  }
  return $articles[$id];
}

然后,一件事是您可以在代码中的任何位置使用此函数。第二件事是您还可以在菜单中使用所谓的 'magic wildcards'。所以你可以有这样的东西:

$items['module/articles/%article'] = array(
    'title' => '',
    'page callback' => 'show_article_page',
    'page arguments' => array(2),
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
 );

这意味着,在 Drupal 调用任何菜单函数回调(页面、访问、标题)之前,它会首先检查名称为 article_load 的函数是否存在存在,将首先调用那个并将结果传递给特定的菜单函数回调。因为 article_load 将静态缓存数据,它会在第一次调用时调用您的网络服务,而在所有其他调用中它只会 return 缓存的文章 object。所以你也可以再次使用标题回调,不要在页面回调中使用drupal_set_title()。

我个人更喜欢第二种方法,因为它允许在请求期间的任何时候加载文章而无需进行额外的外部调用,因此它更通用。

此外,在菜单挂钩中进行更改时不要忘记清除缓存。