УрокБыстрый старт в темизации Drupal
7 мая в Беларуси прошёл Drupal Camp Belarus 2011, где я читал доклад по темизации. Хочу поделиться тем, что я рассказывал народу :)
Краткое введение
Тема сайта – это лицо сайта. Пользователю достаточно нескольких секунд чтобы оценить сайт, понять, нравится он ему или нет. Безусловно, каждый сайт выделяется в первую очередь своим функционалом – сайт никогда не получит большую популярность, имея невероятно красивый дизайн, но бесполезный по своей сути. Однако речь пойдёт именно о темизации, о создании красивого и удобного сайта для пользователя.
Я нередко наблюдал негативные отзывы о Друпале, связанные с легко узнаваемым внешним видом. Т.е. достаточно открыть сайт – и можно сразу уверенно сказать, что сайт сделан с использованием CMF Drupal. Однако эти высказывания применимы лишь для ленивых (начинающих) разработчиков, либо для очень малобюджетных сайтов. В действительности же Drupal имеет огромное количество стандартных средств, при помощи которых можно видоизменить абсолютно любую мелочь, не говоря уже о таких крупных единицах как комментарии, материалы, статьи.
Немного ликбеза
Все темы Друпала, за исключением тех, которые идут в стандартной сборке, должны храниться в папке /sites/all/themes. Сама тема состоит из:
- Файла, в котором описывается тема, версия ядра, подключаемые стили и скрипты и прочее: имя-темы.info
- Файлов стандартных шаблонов вывода содержимого: имя-шаблона.tpl.php
- Файла программной обработки темы: template.php
- Файлов со стилями: имя-файла.css
- Файлов с javascript’ами: имя-файла.js
- Изображения (логотип, скриншот темы, изображения для стилизации)
Единственное, без чего не может существовать тема – это первый пункт списка. Всё остальное по желанию и возможностям.
Подробнее я хочу остановиться именно на втором и третьем пункте списка – а именно на файлах вывода содержимого и файле программной обработки темы, т.к. именно они подготавливают содержимое к выводу.
Вывод содержимого через файлы .tpl.php
В эти файлы из модулей передаётся набор переменных, определённых разработчиком, содержащих контент для вывода.
В Друпале существует набор стандартных файлов шаблонов .tpl.php, которые желательно иметь у себя в теме для свободного изменения внешнего вида. По умолчанию они все лежат в системных модулях, и содержимое выводится именно через них. Однако стоит положить эти файлы к себе в тему и очистить кэш – как содержимое будет выводиться уже через шаблоны внутри темы. Их можно менять внутри, дописывать или удалять свои строки – всё это и есть неотъемлемая часть темизации. Отсюда очевидный плюс – мы не трогаем содержимое модулей, для изменения вывода их содержимого. То есть модули можно обновлять, не опасаясь за возможные проблемы с внешним видом сайта.
Вот список файлов шаблонов, наиболее часто встречающихся в темах:
- page.tpl.php – сюда передаются переменные с содержимым страницы. Здесь можно найти подключение скриптов, стилей, вывод заголовка страницы, его содержимого, системных сообщений и прочих элементов страницы.
- maintenance-page.tpl.php – шаблон, отвечающий за вывод страницы сайта, когда он стоит режиме техобслуживания. Передаются те же переменные, что и в page.tpl.php
- node.tpl.php – сюда передаётся вся информация о выводимом материале – заголовок, содержимое, автор, его таксономия и прочее
- block.tpl.php – находится информация о выводом блоке – заголовок, содержимое, модуль, которым он был создан (если создан не руками), и т.д.
- comment.tpl.php – передаются переменные с содержимым выводимого комментария – заголовок, содержимое, автор, и пр.
- Остальные файлы уже добавляются при необходимости, и берутся они, как я уже говорил, из папки с модулем, вывод которого необходимо переопределить.
Пример работы с файлом node.tpl.php
Содержимое этого файла по умолчанию:
<div id="node-<?php print $node->nid; ?>" class="node<?php if ($sticky) { print ' sticky'; } ?> <?php if (!$status) { print ' node-unpublished'; } ?> clear-block"> <?php print $picture ?> <?php if (!$page): ?> <h2><a href="<?php print $node_url ?>" title="<?php print $title ?>"><?php print $title ?></a></h2> <?php endif; ?> <div class="meta"> <?php if ($submitted): ?> <span class="submitted"><?php print $submitted ?></span> <?php endif; ?> <?php if ($terms): ?> <div class="terms terms-inline"><?php print $terms ?></div> <?php endif;?> </div> <div class="content"> <?php print $content ?> </div> <?php print $links; ?> </div>
Вот так выглядит вывод содержимого через этот файл:
На картинке обычный текст - т.к. заголовок в полной версии материала не выводится (по умолчанию), ссылок и таксономии тут тоже нет.
А теперь скопируем этот файл к себе в тему и немного темизируем его:
<div id="node-<?php print $node->nid; ?>" class="node<?php if ($sticky) { print ' sticky'; } ?> <?php if (!$status) { print ' node-unpublished'; } ?> clear-block"> <div class = "created-by"> <?php print $variables['created_by'] = t('This @type was created by !author at %date', array( '@type' => $node->type, '!author' => $name, '%date' => date('d.m.Y H:i', $node->created) )); ?> </div> <?php print $picture ?> <?php if (!$page): ?> <h2><a href="<?php print $node_url ?>" title="<?php print $title ?>"><?php print $title ?></a></h2> <?php endif; ?> <div class="meta"> <?php if ($submitted): ?> <span class="submitted"><?php print $submitted ?></span> <?php endif; ?> <?php if ($terms): ?> <div class="terms terms-inline"><?php print $terms ?></div> <?php endif;?> </div> <div class="content"> <?php print $content ?> </div> <?php print $links; ?> </div>
Теперь перед началом статьи располагается надпись о том, кем и когда был создан этот тип материала:
Темизировать шаблоны вывода содержимого можно как используя стандартные переменные, которые передаются в эти шаблоны, так и создавая свои шаблоны. Стандартные переменные, которые передаются в эти шаблоны абсолютно не засекречены, и найти их можно либо в самом файле на английском языке (если брать из модуля) либо вот тут, но на русском: http://drupalace.ru/uroki, либо просто поискать на просторах веба.
Теперь о том, как в шаблоны вывода эти файлы попадают.
Функции предварительной обработки переменных
В Друпале существуют функции, позволяющие централизовано собрать все необходимые данные для передачи их в файлы шаблонов. Что более важно – их можно перекрывать в своей теме, а именно в файле template.php, где должен храниться весь код темы.
Название таких функций выглядят следующим образом: template_preprocess_ключ. Здесь ключ выбирается не случайным образом. Он должен совпадать с ключом массива, возвращаемое в модуле через hook_theme, но это не предметом моей статьи, поэтому я на этом не буду заострять внимания. Главное запомнить эти названия для основных шаблонов вывода материалов. А сделать это нетрудно, т.к. они совпадают с названием самих шаблонов:
- template_preprocess_page
- template_preprocess_node
- template_preprocess_block
- template_preprocess_comment
В качестве параметра функции передаётся массив с переменными, которые можно использовать как в функции предобработки, так и в самом шаблоне вывода содержимого. Хочу заметить, что эти функции являются абсолютно необязательными в модуле – если их не будет, переменные из нужных функций всё равно дойдут до файлов шаблона вывода. Однако, скорее всего, нам придётся писать код прямо в шаблоне, чтобы их обработать нужным образом и вывести. А большое количество кода в файле шаблона смотрится ну очень некрасиво, да и неправильно это с точки зрения Друпала.
Так вот, чтобы перекрыть функцию предварительной обработки переменных у себя в теме необходимо слово template в названии функции заменить на имя темы. Например, для темы garland функция будет выглядеть так:
function garland_preprocess_page(&$variables) { // Some code }
Как я уже говорил, в этой функции можно создавать и свои переменные для передачи их в шаблон. А так же, я говорил что лишний код в шаблонах – это плохо. Сейчас я объединю эти два утверждения и исправлю то, что сделал немного выше. А именно – уберу темизированную часть из node.tpl.php и положу его в функцию предварительной обработки материала в template.php, затем создам дополнительную переменную, и верну её обратно в node.tpl.php. Вот как это выглядит на практике (работа ведётся в теме garland):
*функция добавлена в template.php*
/** * Override or insert node variables into the node.tpl.php */ function garland_preprocess_node(&$variables) { $variables['created_by'] = t('This @type was created by !author at %date', array( '@type' => $variables['node']->type, '!author' => $variables['name'], '%date' => date('d.m.Y H:i', $variables['node']->created) )); }
Содержимое node.tpl.php:
<div id="node-<?php print $node->nid; ?>" class="node<?php if ($sticky) { print ' sticky'; } ?> <?php if (!$status) { print ' node-unpublished'; } ?> clear-block"> <div class = "created-by"> <?php print $created_by; ?> </div> <?php print $picture ?> <?php if (!$page): ?> <h2><a href="<?php print $node_url ?>" title="<?php print $title ?>"><?php print $title ?></a></h2> <?php endif; ?> <div class="meta"> <?php if ($submitted): ?> <span class="submitted"><?php print $submitted ?></span> <?php endif; ?> <?php if ($terms): ?> <div class="terms terms-inline"><?php print $terms ?></div> <?php endif;?> </div> <div class="content"> <?php print $content ?> </div> <?php print $links; ?> </div>
Результат остался неизменным:
Отдельно хочу отметить важность работы с функциями предварительной обработки переменных из-за следующей переменной: $variables[‘template_files’]. Она хранит в себе возможные шаблоны перекрытия шаблона вывода, уточнив его каким-либо параметром. Поясню на примере. В стандартной функции предобработки переменных для страницы имеет место быть следующий код:
$i = 0; $suggestion = 'page'; $suggestions = array(); while ($arg = arg($i++)) { $arg = str_replace(array("/", "\\", "\0"), '', $arg); $suggestions[] = $suggestion .'-'. $arg; if (!is_numeric($arg)) { $suggestion .= '-'. $arg; } } if (drupal_is_front_page()) { $suggestions[] = 'page-front'; } if ($suggestions) { $variables['template_files'] = $suggestions; }
Он позволяет создать отдельный шаблон для абсолютно любой страницы. Т.е. я могу создать шаблон page-node-1.tpl.php (скопировав туда всё содержимое page.tpl.php), потом оставить там только вывод заголовка страницы и всунуть, например баннер. Далее пользователь, который зайдёт на страницу /node/1 увидит лишь заголовок страницы и баннер. Все же остальные материалы останутся без изменений. Т.е. в шаблон можно вписать любые аргументы урла из адресной строки – и для этой страницы будет создан собственный шаблон. Например, страницу http://example.ru/node/add/new можно перекрыть шаблоном page-node-add-new.tpl.php. Если нет такого шаблона, то Друпал будет искать шаблон page-node-add.tpl.php, далее page-node.tpl.php, и потом уже вернётся к родному page.tpl.php. Для главной страницы предусмотрен шаблон page-front.tpl.php.
Для материала, например, можно создавать шаблоны по принципу node-номерСтатьи.tpl.php. Т.е. для материала с уникальным идентификатором 232 шаблон будет выглядеть так: node-232.tpl.php.
Более того, Друпал позволяет создавать собственные шаблоны. Главное правильно задать условие работы шаблонов.
Пример: необходимо создать шаблон страницы, который будет отображён в зависимости от типа материала. Решение:
/** * implementation of template_preprocess_page() */ function ИМЯТЕМЫ_preprocess_page(&$variables) { if (isset($variables['node']) && $variables['node']->type) { $variables['template_files'][] = 'page-node-type-'.$variables['node']->type; } }
Теперь, например, для типа материала story шаблон выглядит page-node-type-story.tpl.php. Можно зайти в этот шаблон и поменять/добавить/удалить элементы страницы. Данное изменение коснётся только материалы типа story и только при полном просмотре статьи.
- Spleshka
- 08.05.2011
- 33975
Комментарии
Отличная статья , спасибо!
А так можно сделать?
node-type-story.tpl.php для переопределение вывода данных для типа story? Или надо писать Вашу заглушку в конце статьи?
не node-type-story.tpl.php, а node-story.tpl.php - это стандартный шаблон, заглушек писать не надо
Что-то в семерке это не работает.
Так уточнять надо под какой Drupal ;)
в 7ке это то ли node--story.tpl.php, то ли node__story.tpl.php, попробуй оба варианта
К сожалению, не удалось связаться с Вами ни по Скайпу, ни по Аське. Имя файла подтянулось (первый вариант). А как узнать какие переменные доступны в этом файле?
print_r($node);
не подскажите где можно изучить вопрос темизации для 7-ки только, желательно поподробнее
спс за статью
Подскажите, если не сложно а если захотеть иметь 2 возможности вывода форм.
Ну например по ссылке node/add/page мне нужна стандартная фома, а по ссылке node/add/page/ajax я хочу чтобы клиенту drupal возвращал только тело формы. Как такое реализовать??
Ой все поразмыслив понял.
page-node-add-page-ajax.tpl.php
Сам себе и ответил. СПАСИБО ЗА СТАТЬЮ.
.....Например, страницу http://example.ru/node/add/new можно перекрыть шаблоном page-node-add-new.tpl.php.
Создал page-node-add-new.tpl.php пустой, даже page-node-add.tpl.php ну никак не могу понять как перекрыть, поясните.
Если 6й друпал - просто сбросьте кэш и всё подцепится. Если седьмой, то шаблон должен быть page--node--add--new.tpl.php, после чего опять же - сбросьте кэш.
Всё на 7-ке. Спасибо сработало, действительно, кэш - моз выносил (чёт с одного раза не скидывается, в производительности все галочки сняты, в браузере Ф5, очищал все кэши но с первого раза не работает ??????... )
Прошу вновь пояснить, у вас на сайте только правый блок, я хочу так же, но только на определённых типах материала, создал page--report.tpl.php (скопировав содержимое простого page.tpl.php) удалил левый блок в шаблоне (с кэшем боролся, как выше писал) - опять нет результата. Разжуйте если можно, у вас это чинно получается :))))
Что-то не получается создать переменную
В node.tpl.php. вставляю
print $ima;
и ничего не выводится, а если просто. весть код в файл ноды вставляю, картинка отображаетсяЕстественно вставляю
Нужно было писать так:
Столько статей прочла про темизацию и впервые нашла действительно очень полезный материал-сразу видно, что рассказывает профессионал. Спасибо. Действительно интересно
С позволения автора выложу здесь пдф-ку - структурированный список всех переменных и порядок именования шаблонов в друпал 7. Очень полезная штука. Ссылка на обменник
Комментировать