Немного о создании шаблонов для joomla 3

Решил поделиться некоторыми знаниями с начинающими разработчиками под cms Joomla. Здесь не будет описана конкретно разработка шаблона, но будет рассказано о моментах, знание которых может пригодится. Если же вашей целью является именно изучение с нуля, можете погуглить еще или например глянуть тут.

При разработке сайта на joomla основным моментом является разработка шаблона (если конечно не используется готовый, тогда разработки и нет вовсе). В действительности, шаблон это немного больше чем просто макет, в него можно добавлять свои функции. То есть по сути в шаблоне может быть реализована некая нестандартная функциональность. Благодаря этому были созданы некоторые фреймворки, которые позволяют ускорять разработку шаблонов. Они представляют из себя заготовку шаблона, с множеством блоков и своим API. Некоторые из них даже расширяют функциональность административной панели, позволяя гибко настраивать различные блоки не прибегая к программированию. Самым популярным фреймворком является «T3 template framework». Однако, начинающему программисту, хотя бы пару раз стоит создать шаблон своими руками.

Прежде всего необходимо знать, что на самом деле, вы можете запрограммировать шаблон как вам угодно. Я имею в виду, что вы можете делать структуру папок и файлов шаблона как хотите. Шаблон имеет всего два реально важных файла: index.php и templateDetails.xml.
Именно с index.php все и начинается. Что в нем будет, верстка вперемешку с кодом или инициализация фреймворка — это уже ваше личное дело. Исключением, пожалуй, является директория html, которая необходима, если вы собираетесь переопределять шаблоны модулей или компонентов. Файл templateDetails.xml как можно догадаться, содержит описание шаблона: название, автор, файлы и директории, позиции, параметры и тп.
Таким образом самый минимальный шаблон будет выглядеть так:
templateDetails.xml

<?xml version="1.0" encoding="utf-8"?>
<extension version="1.0" type="template" client="site">
    <name>My_Temlate</name>
    <creationDate>2014-12-01</creationDate>
    <author>Me</author>
    <authorEmail>mail@site.ru</authorEmail>
    <authorUrl>http://site.ru/</authorUrl>
    <copyright>Me 2014</copyright>
    <license>Private</license>
    <version>1.0.0</version>
    <description>My template</description>
    <files>
        <filename>index.php</filename>
        <filename>templateDetails.xml</filename>
    </files>
    <positions>
        <position>top-nav</position>
        <position>footer</position>
    </positions>
</extension>

index.php

<?php
/**
 * My template
 */
?><!DOCTYPE html>
<html lang="<?= $this->language ?>" dir="<?= $this->direction ?>">
<head>
    <meta charset="utf-8">
    <jdoc:include type="head" />
</head>
<body>
    <jdoc:include type="modules" name="top-nav"/>
    <jdoc:include type="component" />
    <jdoc:include type="modules" name="footer"/>
</body>

Если запаковать эти два файла в zip, то получившийся шаблон можно будет инсталлировать через менеджер расширений.

Примечание
Стоит упомянуть пару особенностей конструкции <jdoc:include/>, знание которых убережет вас от ошибки. В jdoc:include очень важна последовательность атрибутов и их наличие. Как по мне, это просто недоработки самой joomla и по логике вещей, такого быть не должно, но, это есть.
Итак, не будет работать:
— запись вида <jdoc:include name="top-nav" type="modules"/>, потому что атрибут type просто обязан быть первым. Это связано с регулярым выражением в парсере.
— запись вида <jdoc:include type="component" name="position-content"/>, потому что для type="component" недопустим атрибут name. Иначе это считается обычной позицией для модуля (странно да?). Так что не стоит бездумно «копипастить» код позиций просто меняя в них значение аттрибута type, нужно еще следить за указанными атрибутами.

Не лишним будет понимание того, как именно происходит процесс обработки вашего шаблона. Вот краткий список этапов:

  1. Загрузка ядра системы, инициализация
  2. Загрузка плагинов и вызов некоторых триггеров
  3. Загрузка списка активных модулей и компонентов
  4. Запуск на выполнение вашего шаблона (точнее файла index.php), результат работы не выводится в браузер, а сохраняется в переменной. Здесь отрабатывает вся логика шаблона, то есть на выходе получится итоговый html код, но без контента и модулей.
  5. Парсинг вашего шаблона (из переменной) и поиск всех служебных конструкций вида «jdoc:include», их замена на модули и компоненты в соответствии с запрошенным адресом страницы.
  6. Снова вызов некоторых триггеров для плагинов (плагины могут вносить изменения в получившийся html код, например стилизация таблиц)
  7. Вывод результата в браузер

Еще раз отмечу, что тут описаны не все этапы, а только нужные для понимания того, в каком порядке и что вызывается.

Теперь немного о ключевом слове $this. Дело в том, что index.php из вашего шаблона вызывается не сам по себе, а внутри специального класса JDocumentHTML. Поэтому внутри вашего шаблона, переменная $this указывает на его объект и позволяет вам манипулировать шаблоном и получать некоторые данные о текущей странице.
Для любопытных привожу код метода этого класса, в котором происходит загрузка шаблона.

protected function _loadTemplate($directory, $filename)
{
    $contents = '';  // вот сюда будет сохранен результат работы вашего шаблона
    if (file_exists($directory . '/' . $filename)) // проверяется существование стартового файла шаблона
    {
        $this->_file = $directory . '/' . $filename;
        ob_start(); // включается буферизация, что препятствует попаданию результата в браузер
        require $directory . '/' . $filename; // запуск вашего шаблона
        $contents = ob_get_contents(); // запись результата в переменную
        ob_end_clean(); // очистка буфера
    }
    // ... остальная часть кода опущена, она не столь важна для понимания
    return $contents; // теперь полученный html код отправляется на парсинг и прочие процедуры ;)
}

Но вернемся к ключевому слову $this. Что же оно позволяет нам делать? Чаще всего в статьях о разработке шаблонов для joomla встречаются такие вызовы:

  • $this->_charset — кодировка страниц
  • $this->language — язык сайта
  • $this->direction — направление текста (слева-направо или справа-налево)
  • $this->title — заголовок сайта
  • $this->baseurl — базовый url сайта (то есть корень). Используется для подключения скриптов и стилей
  • $this->template — имя папки шаблона (не полный путь, а только имя папки)
  • $this->countModules('position_name') — получение количества модулей в определенной позиции

Но ни слова о том, что такое $this и что еще он позволяет делать. Чтобы разобраться в этом, достаточно открыть файл /libraries/joomla/document/html/html.php и просмотреть список методов и свойств класса. Что можно там найти:

  • $this->_file — полный путь на диске до вашего index.php файла. Можно использовать для получения пути до корня шаблона с помощью dirmane($this->_file) (что в принципе равносильно dirname(__FILE__), но работает в любом подключенном файле, а не только в index.php);
  • $this->_links — массив всех тегов link подключенных системой или другими расширениями (они выводятся вместо тега <jdoc:include type="head">);
  • $this->_custom — массив всех произвольных тегов подключенных системой или другими расширениями;
  • $this->getHeadData() — массив всех подключенных тегов script, link, meta и т.д. включая пользовательские вставки js скриптов;
  • $this->addHeadLink() — позволяет программно добавить тег link в head шаблона;
  • $this->addFavicon() — позволяет программно установить иконку сайта (например, если она задается из настроек шаблона в админке);
  • $this->addCustomTag() — позволяет программно добавить произвольный тег в head шаблона;
  • $this->countMenuChildren() — позволяет определить количество подпунктов текущего активного пункта меню (если они есть);
  • $this->params ссылается на объект с параметрами шаблона, которые могут быть описаны в файле
    templateDetails.xml.

Например, если добавить templateDetails.xml такой блок с параметром (логотип сайта):

<config>
    <fields name="params">
        <fieldset name="advanced">
            <field name="logo"
                   type="media"
                   default="/templates/TEMPLATE_NAME/default-logo.png"
                   label="Логотип"/>
        </fieldset>
    </fields>
</config>

Тогда прочитать параметр в шаблоне можно будет так:

<img src="<?= $this->params->get('logo') ?>" alt="лого"/>

Кроме того, сам класс JDocumentHTML унаследован от другого класса JDocument (/libraries/joomla/document/document.php), следовательно мы можем использовать и его методы и свойства, именно там содержатся такие как $this-title, $this->languadge. Там также можно найти:

  • $this->description — описание страницы (тег meta description);
  • $this->base — полный путь текущей страницы (http://site.ru/pagename.html)
  • $this->_generator — тот самый текст ‘Joomla! — Open Source Content Management’ выводимый в meta тег generator. Чтобы убрать эту надпись просто присвойте свойству пустую строку: $this->_generator = '';
  • $this->setMetaData() — добавить какой-нибудь meta тег;
  • $this->addScript() — добавить ссылку на javascript (тег <script>). Есть еще метод addScriptVersion() который делает то же самое, но позволяет добавлять версию файла, чтобы бороться с кешированием измененных скриптов;
  • $this->addScriptDeclaration() — добавляет код javascript непосредственно в тег head. Например, инициализация слайдера;
  • $this->addStyleSheet() и $this->addStyleSheetVersion() — добавление ссылок на файл стилей;
  • $this->addStyleDeclaration() — добавляет описание стилей непосредственно в тег head;
  • $this->setCharset() и $this->getCharset() — геттер и сеттер для и без того публичного свойства $this->_charset (странно). Аналогично для свойств $this->languadge, $this->direction, $this->title и т.д.;

Зачастую всего этого бывает недостаточно, поэтому обычно пользуются еще одним объектом:

// получаем ссылку на объект нашего приложения
$app = JFactory::getApplication(); // (класс JApplicationSite /libraries/cms/application/site.php)

С помощью полученного объекта можно читать данные нашего приложения (сайта). Например, получить пункты меню или определить, является ли текущая страница главной (homepage). Вот пример функции, которая поможет это узнать:

function is_mainPage(){
    $menu = JFactory::getApplication()->getMenu();
    return ($menu->getActive()->id == $menu->getDefault()->id) ? true : false;
}

Вообще, объект Application содержит большое количество свойств и методов, так как имеет 4 уровня наследования (JApplicationSite -> JApplicationCms -> JApplicationWeb -> JApplicationBase). Но большая часть этих плюшек не применима в контексте выполняющегося шаблона. Я выделю лишь несколько из них, которые по моему мнению могут пригодиться. Вас же, ничто не удерживает от экспериментов 😉

В списке ниже подразумевается, что $app = JFactory::getApplication();

  • $app->redirect($url) — редирект на другую страницу;
  • $app->getMenu() — возвращает объект меню;
  • $app->get(config_param) — возвращает значение параметра из конфигурации сайта (файл configeration.php). Например, можно получить e-mail администратора $app->get('mailfrom') или название сайта $app->get('sitename');
  • $app->isAdmin() — возвращает true, если текущий пользователь является администратором;

Вот в общем-то и все, о чем я хотел рассказать. Прошу дополнять в комментариях, если я упустил из виду что-то интересное. Буду очень признателен.

This entry was posted in Заметки, Прочее and tagged . Bookmark the permalink.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать язык разметки Markdown

Protected by WP Anti Spam