每种内容类型的预处理功能


25

我有几种内容类型,需要以不同的方式进行预处理。所以template.php在我的主题中foo当前看起来像:

function foo_preprocess_node(&$variables) {
    if ('news' ==$variables['type']) _preprocess_news($variables);
    if ('event'==$variables['type']) _preprocess_event($variables);
    if ('alert'==$variables['type']) _preprocess_alert($variables);
    ...
}

function _preprocess_news(&$variables) {
    ...
}

function _preprocess_event(&$variables) {
    ...
}

function _preprocess_alert(&$variables) {
    ...
}

我希望能够指定特定于Drupal的预处理功能,该功能将与内容类型的计算机名称挂钩。我尝试使用,foo_preprocess_news但从未调用过。

有没有更好的办法?

Answers:


10

预处理功能的名称基于主题名称,因此theme_table()您的预处理功能为MYTHEME_preprocess_table()

由于没有theme_node_node_type功能的预处理挂钩,如foo_preprocess_newsfoo_preprocess_node_news不箱子的工作了。

可以重写主题注册表,以使它在节点上的行为有所不同,但是我真的不建议这样做。它可能会变得非常混乱。

我是重构代码的忠实拥护者,但在您的情况下,我认为这不是必需的。如果您有复杂的逻辑需要根据节点类型在预处理挂钩中运行,那么按照您目前的方式将其种植到不同的功能上,对我来说似乎是一种好习惯。

当然,另一种方法是为每种不同的内容类型实现一个定制模块,并hook_preprocess_node()在每种类型中实现。这样,每个模块的预处理功能可以负责不同的内容类型。

但是,这对于您的情况可能是过大的;如果您没有对每种内容类型执行额外的逻辑(即非主题预处理逻辑),则此方法可能不会增加任何额外的值。


1
好。我也可以foo_preprocess_node通过实现它来“自动化” 它,call_user_func('_preprocess_' . $vars['type'], $vars);以避免重复ifs,但最好还是保持简单。
cherouvim 2012年

hook_preprocess_node()在一个自定义模块上实现,并希望在钩子被调用时会有所限制,但事实并非如此。有什么方法可以限制挂钩由内容类型调用的时间?
凯文(Keven)2015年

@Keven如果函数存在,您不能停止调用它,但是if ($vars['node']->type == 'foo') { ...会达到您想要的效果
Clive

我真的只是在寻找一些细微的优化,类似于您可以使用的优化hook_block_view_MODULE_DELTA_alter()。我目前正在按照您说的去做,但希望有一种方法可以限制钩被撞到的时间。
凯文(Keven)2015年

尽管@Keven并不是最佳选择-您只是将决策过程转移到了代码的另一部分。实际上,如果Drupal提供了这样的覆盖,则它需要是通用的,并且几乎可以肯定会花费更多的处理器时间来完成。你已经通过只是在最后时刻做出决定获胜
克莱夫

28

zen子主题通过将其添加到其theme_preprocess_node函数来实现此目的:

function foo_preprocess_node(&$variables, $hook) {
  ...
    // Optionally, run node-type-specific preprocess functions, like
  // foo_preprocess_node_page() or foo_preprocess_node_story().
  $function = __FUNCTION__ . '_' . $variables['node']->type;
  if (function_exists($function)) {
    $function($variables, $hook);
  } 
  ...
}

如果您的内容类型为“ news”,则可以在template.php文件中创建一个名为foo_preprocess_node_news的函数。


我们还在ZURB基础上将此代码与我们自己的实现(非常有用的代码段)一起使用。
Marko Blazekovic

2

我只有一个类似的问题,这就是Google为什么将我带到此页面的原因:我的节点预处理功能变得非常大,以至于我宁愿将该功能拆分为多个文件。

我已经在template.php文件中完成了类似的方法,该文件包含了所有的alter函数,并且由于相同的方法在这里可以很好地工作,所以我想我应该分享一下我的方法:

文件夹内的文件设置MYTHEME/preprocess

- node.preprocess.inc
- node--blog-post.preprocess.inc
- node--device-variation.preprocess.inc
- (...)

您应该已经拥有node.preprocess.inc,您可以创建自己的其他人。您如何称呼它们确实是很随意的,但最好给它们起一个能很好地识别它们并适合整个drupal命名系统的名称。
从这些文件的内容开始!

node.preprocess.inc,这里我正在做这样的事情:

<?php

function MYTHEME_preprocess_node(&$variables) {

    switch($variables['type']) {

      case 'blog_post':
        // if the type of the node is a Blog Post, include this:
        include 'node--blog-post.preprocess.inc';
        break;

      case 'device_variation':
        // if Device Variation, include this:
        include 'node--device-variation.preprocess.inc';
        break;

      case 'foo':
        // ...
        break;
    }

    // additional stuff for all nodes

}

我们基本上会切换当前节点的类型。您的选择取决于您;#id,,#view_mode这完全取决于您的实际需求。
一旦存在匹配项,它将加载指定的文件并对其内容执行操作,就好像它是直接在此函数中编写的一样。

这些included文件的内容与您将其放入文件中的样子完全一样node.preprocess.inc,只是我们不再调用预处理函数:

node--device-variation.preprocess.inc

<?php

    // Device Name
    $device = drupal_clean_css_identifier(strtolower($variables['title']));

    // Determine whether only Device Version is of type 'N/A' and set ppvHasVariations accordingly
    $deviceHasVariations = true;
    if( $variables['content']['product:field_model_variation'][0]['#options']['entity']->weight == 0 ) {
        $deviceHasVariations = false;
    }
    //...

您基本上可以使用任意数量的文件来执行此操作,甚至可以级联多个开关,例如根据进一步拆分特定的节点预处理文件#view_mode,其中一个用于full查看模式,另一个用于teaser

希望这会有所帮助,如果有人再次偶然发现此问题(:


1

call_user_func()不会通过引用传递参数。因此,在$variables您的preprocess_foo()函数仅适用于原始数组副本的情况下;在其余渲染过程中,对非对象的更改将不适用。


1

在您的主hook_preprocess_node中,最后实现以下代码

$preprocess_function = 'themename_node__' . $node->type . '__preprocess';
if (function_exists($preprocess_function)) {
 $preprocess_function($variables);
}

所以您现在可以按节点类型进行预处理

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.