УрокФункции предобработки переменных перед выводом в шаблон

Все мы знакомы с обычными файлами шаблонов, выглядящими по принципу файл.tpl.php. И все привыкли, что в этом шаблоне откуда-то (магия?) появляются переменные с даннами. Сегодня я приоткрою эту тайну: для того, чтобы попасть в шаблон, была придумана функция предобработки переменных. Обычно она выглядит вот таким образом:

  function template_preprocess_что_обрабатываем(&$variables) {
    //код
  }

где

  • template- это имя темы или модуля (в зависимости от того, где реализуем функцию)
  • $variables - массив с доступными переменными
  • preprocess_что_обрабатываем - собственно, название функции с говорящим названием :)

Как пример - в каждой теме присутствует файл page.tpl.php. Функция, которой можно обработать этот файл - template_preprocess_page.

Давайте посмотрим небольшой кусок этой функции (ссылка api.drupal.ru):

  $variables['head_title']        = implode(' | ', $head_title);
  $variables['base_path']         = base_path();
  $variables['front_page']        = url();
  $variables['breadcrumb']        = theme('breadcrumb', drupal_get_breadcrumb());
  $variables['feed_icons']        = drupal_get_feeds();
  $variables['footer_message']    = filter_xss_admin(variable_get('site_footer', FALSE));
  $variables['head']              = drupal_get_html_head();
  $variables['help']              = theme('help');
  $variables['language']          = $GLOBALS['language'];
  $variables['language']->dir     = $GLOBALS['language']->direction ? 'rtl' : 'ltr';
  $variables['logo']              = theme_get_setting('logo');

Здесь генерируются переменные. Откуда они берутся - ну, собственно, кто откуда :) Главная идея в том, что в итоге получается массив $variables, элементы которого передаются в шаблон page.tpl.php. Это именно те переменные, с которых у многих людей начиналась работа со своими темами. Теперь вы знаете, откуда они взялись!

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

Пример 1

Например, работаем мы со стандартной темой Garland. И допустим, я захотел, чтобы во всех нодах типа news заголовком страницы ($title) являлся текст "Новости". В template.php пишем такой код:

 
 
// заменяем в template_preprocess_page слово
// template на название нашей темы
function garland_preprocess_page(&$variables) {
 
  // теперь проверяем, если в массиве переменных
  // была передана переменная node (а она появляется только
  // на страницах, содержащих материал), и тип материала - новость,
  // то переменной заголовка присваиваем новое значение - 'Новость'
  if (isset($variables['node'])) {
    if ($variables['node']->type == 'news') {
      $variables['title'] = 'Новости';
    }
  }
}

Теперь на всех страницах нод новостей, в переменной $title шаблона page.tpl.php будет красоваться надпись "Новости".

Пример 2

Пусть мы работаем всё с той же старой и надёжной темой Garland. Но теперь у меня задача - вывести в блок дополнительные классы для css, характеризующие этот блок. За предобработку переменных для блока отвечает функция template_preprocess_block:

function garland_preprocess_block(&$variables) {
 
  // получаю данные о блоке
  $block = $variables['block'];
 
  // инициализирую массив будующих классов
  $block_classes = array();
 
  // в первую ячейку массива пишу строку, со значением модуля, которым 
  // был создан блок
  $block_classes[] = 'block-'. $block->module;
 
  // во вторую ячейку отправилась "четность" блока, 
  // тоесть odd или even
  $block_classes[] = $variables['zebra'];
 
  // третья ячейка - порядковый номер блока в регионе
  $block_classes[] = 'block-'. $variables['block_id'];
 
  // теперь делаем из нашего массива одну строку, 
  // предварительно разделив бывшие ячейки массива пробелами,
  // и создаём в файле block.tpl.php новую переменную $classes
  $variables['classes'] = implode(' ', $block_classes);
}

Теперь в block.tpl.php стала доступна переменная $classes, которую можно использовать, например, вот так (содержимое файла block.tpl.php):

<div id="block-<?php print $block->module .'-'. $block->delta; ?>" class="block <?php print $classes; ?>">
 
  <?php if ($block->subject): ?>
    <h2 class="block-title"><?php print $block->subject; ?></h2>
  <?php endif; ?>
 
  <div class="block-content">
    <?php print $block->content; ?>
  </div>
 
</div>

Вот и вся хитрость. Просто, не так ли?

Кстати, с помощью функций предобработки можно создавать кастомные (свои) файлы шаблонов. Как пример - создание отдельного шаблона страницы для разных типов ноды

Комментарии

Аватар пользователя Тайный поклонник
Тайный поклонник написал:

Супер, спасибо за статью.
ПС
user warning: Unknown column 'captcha_type' in 'field list' query: SELECT module, captcha_type FROM captcha_points WHERE form_id = 'comment_form' in /home/u3146/domains/drupalace.ru/sites/all/modules/captcha/captcha.inc on line 60.
user warning: Unknown column 'captcha_type' in 'field list' query: SELECT module, captcha_type FROM captcha_points WHERE form_id = 'user_login_block' in /home/u3146/domains/drupalace.ru/sites/all/modules/captcha/captcha.inc on line 60.

16.02.2011 09:20
Аватар пользователя Бешеный стопицоткрыл
Бешеный стопицоткрыл написал:

user warning: Unknown column 'captcha_type' in 'field list' query: SELECT module, captcha_type FROM captcha_points WHERE form_id = 'comment_form' in /home/u3146/domains/drupalace.ru/sites/all/modules/captcha/captcha.inc on line 60.

update.php забыл, штоли? =D

16.02.2011 09:25
Аватар пользователя Spleshka
Spleshka написал:

Ага)) Когда заканчиваешь работу над сайтом в 4 утра, всегда есть шанс что-то упустить ))

16.02.2011 13:31
Аватар пользователя AK47
AK47 написал:

SplasH, Спасибо ! Как всегда о непонятном, простым языком :)

17.02.2011 20:16
Аватар пользователя Spleshka
Spleshka написал:

Спасибо, стараюсь :)

17.02.2011 21:45
Аватар пользователя otmoroz095
otmoroz095 написал:

а как получить все переменные пользователя, включая аватар и поля профиля?

21.03.2011 16:23
Аватар пользователя otmoroz095
otmoroz095 написал:

хорошо, перефразирую: куда вставить sql запрос для формирования переменных и последующей вставки их в шаблон темы?

22.03.2011 17:40
Аватар пользователя Stown
Stown написал:

Мне тоже интересен этот вопрос. Автор напишите ответ, пожалуйста.

17.07.2012 15:06
Аватар пользователя Тайный поклонник
Тайный поклонник написал:

а возможно ли следующее: создана "запись в блоге" и выводятся ссылки "блог !username" "комментировать" "читать далее". Так вот, мне нужно что бы слово блог было одного цвета, а слово !username другого цвета, но из - за того что это одна ссылка нет возможности этого реализовать, как можно !username обернуть в div?

01.06.2011 13:09
Аватар пользователя Spleshka
Spleshka написал:

Как минимум 2 варианта:

  • Создать модуль. Назовём, например, bloglink.
    Создать файлы bloglink.info и bloglink.module. Положить их в папку /sites/all/modules/blogapi на вашем сервере.

    Содержимое bloglink.info:

    name = Bloglink
    version = VERSION
    core = 6.x

    Содержимое файла bloglink.module:

    <?php
     
    /**
     * Implementation of hook_link().
     */
    function bloglink_link($type, $node = NULL, $teaser = FALSE) {
      $links = array();
     
      if ($type == 'node' && $node->type == 'blog') {
        if (arg(0) != 'blog' || arg(1) != $node->uid) {
          $node->links['blog_usernames_blog'] = array( 
            'title' => 'Блог <span>'. $node->name .'</span>',
            'href' => "blog/$node->uid",
            'attributes' => array('title' => t("Read !username's latest blog entries.", array('!username' => $node->name))),
            'html' => true,
          );
        }
      }
     
      return $links;
    }

    Я конечно модуль не тестировал - если будут ошибки пишите :) Но по идее не должны возникнуть. После включения модуля имя пользователя будет обёрнуто в <span>

  • Переписать ссылку, выводимую модулем blog в своей теме. Для этого откройте template.php вашей темы и напишите там такой код:

    <?
    function ИМЯТЕМЫ_preprocess_node(&$variables) {
      $node = $variables['node'];
      if (isset($node->links['blog_usernames_blog'])) {
        $node->links['blog_usernames_blog'] = array( 
          'title' => 'Блог <span>'. $node->name .'</span>',
          'href' => "blog/$node->uid",
          'attributes' => array('title' => t("Read !username's latest blog entries.", array('!username' => $node->name))),
          'html' => true,
        );
        $variables['links'] = theme('links', $node->links, array('class' => 'links inline'));
      }
    }

    Код опять же не тестировался, но теоретически должно работать :) Если будут проблемы - пишите, разберёмся.

01.06.2011 18:23
Аватар пользователя Тайный поклонник
Тайный поклонник написал:

Выбрал второй варинт, но возникла проблема: вставил вашу функцию, переменовал на моё имя темы, очистил кэш, и ссылки вообще пропали

01.06.2011 19:59
Аватар пользователя Spleshka
Spleshka написал:

Сори, забыл переменную скопировать :) Теперь код проверил и исправил. Теперь работает.

01.06.2011 22:24
Аватар пользователя Прохоров
Прохоров написал:

Здрасте.
Я очень новичок в drupale.
Видимо, это статья для d6 написана? Потому что в d7 переменной $variables['title'] или $vars['title'] в template.php нету. Есть $vars['node']->title, однако если её изменять в template.php (равно как и в page.tpl.php или в node.tpl.php) не происходит смены содержимого тега title. Можно было бы подумать, что есть $vars['page']->title но такой нет..
Не могли бы вы разъяснить как в d7 поменять содержимое тега title?

21.09.2011 14:24
Аватар пользователя Spleshka
Spleshka написал:

В D7 тайтл появляется не на этапе предварительной обработки, а в функции обработки - http://api.drupal.org/api/drupal/includes--theme.inc/function/template_process_page/7

21.09.2011 15:18
Аватар пользователя Тайный поклонник
Тайный поклонник написал:

простите, я ответил в общую ветку

21.09.2011 15:38
Аватар пользователя Прохоров
Прохоров написал:

я наверное дико туплю, но функция garland_process_page(&$vars) в template.php не подхватывается (в page.tpl.php тоже). куда её вставлять-то? или может её место в page.tpl.php и надо как-то её вызвать?

21.09.2011 15:37
Аватар пользователя Spleshka
Spleshka написал:

Вы редактируете тему гарланд? Если да, то garland_process_page(&$vars) должна в template.php подхватываться. Если же другая тема - то не garland_process_page, а ИМЯТЕМЫ_process_page

21.09.2011 23:00
Аватар пользователя AmiGator
AmiGator написал:

Лучше бы конечно написать не «ложу строку», а «кладу строку» :-)
а еще лучше в тэгах писать к какой версии друпала относится. так будет понятнее

11.01.2012 16:06
Аватар пользователя Spleshka
Spleshka написал:

Тогда уже "пишу строку". Про версию Друпала давно думал, всё нет времени сделать.

12.01.2012 13:48
Аватар пользователя Zoxx
Zoxx написал:

Попробовал данный пример - в итоге заголовок поменялся только на страницах редактирования нод. В чем может быть проблема?

05.02.2012 22:45
Аватар пользователя Spleshka
Spleshka написал:

Возможно, заголовок ещё где-то перекрывается?

06.02.2012 20:41
Аватар пользователя Stown
Stown написал:

Можно ли в файлах node.tpl.php, page и т.д руками писать теги, а внутрь вставлять переменные со значениями полей? Или нужно обязательно создавать новые переменные с тегами через template_process_ ?

17.07.2012 15:25
Аватар пользователя Олех
Олех написал:

Подскажите, а зачем использовано 2 массива в данном случае?
function theme_preprocess_page(&$vars, &$variables)

07.01.2016 18:06

Комментировать