функция препроцесса для типа содержимого

У меня есть несколько типов контента, которые мне нужно препроцитировать по-разному. Итак, 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, но он никогда не вызывается.

Есть ли лучший способ?

24 голоса | спросил cherouvim 10 PMpTue, 10 Apr 2012 13:57:23 +040057Tuesday 2012, 13:57:23

5 ответов


10

Имя функции препроцесса основано на имени темы, поэтому для theme_table() ваша функция препроцесса MYTHEME_preprocess_table().

Поскольку функция theme_node_node_type отсутствует, обработчик препроцесса, такой как foo_preprocess_news или foo_preprocess_node_news), не будет работать из коробки.

Вы могли переходить в реестр тем, чтобы он вел себя по-разному для узлов, но я бы не рекомендовал его; это может стать очень грязным.

Я большой поклонник кода рефакторинга, но в вашем случае я не думаю, что это необходимо; если у вас сложная логика, которая должна выполняться в вашем предпроцессовом захвате, зависящем от типа узла, то сведение его к различным функциям в том виде, в котором вы сейчас делаете, кажется мне хорошей практикой.

Другим методом, конечно же, было бы реализовать пользовательский модуль для каждого из разных типов контента и реализовать в каждом случае hook_preprocess_node(). Таким образом, функция preprocess каждого модуля может отвечать за другой тип контента.

Однако это может быть излишним для вашей ситуации; если у вас нет дополнительной логики (т. е. логики препроцесса без темы) для каждого типа содержимого, то этот метод, вероятно, не добавляет никакого дополнительного значения.

ответил Clive 10 PMpTue, 10 Apr 2012 14:24:25 +040024Tuesday 2012, 14:24:25
27

Подзаголовок 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);
  } 
  ...
}

Если у вас есть тип контента, называемый «новостями», вы сможете создать функцию, называемую foo_preprocess_node_news, в файле template.php.

ответил Evil E 7 FebruaryEurope/MoscowbThu, 07 Feb 2013 00:27:14 +0400000000amThu, 07 Feb 2013 00:27:14 +040013 2013, 00:27:14
2

У меня только была похожая проблема , поэтому google привел меня на эту страницу: функция preprocess моего узла росла настолько огромной, что я предпочел бы разделить функцию на несколько файлов.

Я уже сделал аналогичный подход в файле 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

надеюсь, что это поможет, если кто-то снова наткнется на этот вопрос (:

ответил Bird-Kid 10 MarpmMon, 10 Mar 2014 19:11:27 +04002014-03-10T19:11:27+04:0007 2014, 19:11:27
1

call_user_func() не передает параметры по ссылке. Таким образом, в случае $variables ваши функции preprocess_foo() будут работать только с копиями исходного массива; изменения в не-объектах не будут применяться во время оставшегося процесса визуализации.

ответил kishkash 17 +04002012-10-17T19:15:09+04:00312012bEurope/MoscowWed, 17 Oct 2012 19:15:09 +0400 2012, 19:15:09
1

В вашем основном hook_preprocess_node Внесите следующий код в конец

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

Итак, у вас теперь будет препроцесс по типу узла

ответил Ziftman 30 J0000006Europe/Moscow 2017, 00:39:04

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132