Немного истории
Возьмем пример: у вас есть материалы с тегами, но компонент обратной связи также использует теги и категории тоже используют теги...
В старой системе шаблонизации, предшествовавшей JLayout (которая по большей части используется до сих пор для отображения представлений), для рендеринга приходилось копировать / вставлять одни и те же HTML-элементы каждый раз, когда нужно было отобразить теги. Это не сложно, не так ли? Но если у нас появляется баг, и кто-то исправляет его для материалов, но забывает исправить для категорий, а затем кто-то добавляет дополнительный функционал, но только для компонента обратной связи... Возникают проблемы, и становится сложнее поддерживать систему.
Для решения этой проблемы, Yannick Gaultier реализовал JLayout
для CMS. Отличная и простая система повторно используемых элементов кода, которая позволяет рендерить HTML из объектов / массивов данных.
Преимущества использования макетов (layouts)
Благодаря системе JLayout мы можем рендерить теги элемента с помощью:
echo JLayoutHelper::render('joomla.content.tags', $itemTags);
По существу, этот код выводит содержимое файла /layouts/joomla/content/tags.php, где $itemTags
является параметром для внутреннего использования. Единственное требование - объект $itemTags
должен иметь одинаковую структуру для всех элементов.
В чем заключаются преимущества данного подхода?
- Повторное использование
Нам нужно поддерживать только один макет. Верстальщику остается настроить его под свои нужды. - Разделение данных и дизайна
Другой замечательной возможностью JLayout является то, что он становится инструментом для разработчика, позволяющим отделить HTML код от PHP. В идеале, 100% разметки должно переопределяться верстальщиком без использования ядра Joomla! Это означает, что если вам нужно загрузить JS файл, вы подключаете его в том месте, в котором верстальщик может переопределить его загрузку - это нужно на случай, если верстальщик решит не использовать ваш JS файл и захочет заменить его другой библиотекой. Сейчас это является наиболее значимой проблемой в Joomla и является причиной, по которой разработчики бегут от страха после некоторого времени, проведенного с Joomla. - Простая интеграция с 2.5.x
Система макетов - всего 4 файла. Вы можете подключить их в свою библиотеку для поддержки 2.5 и /или расширить их с помощью своих классов.
Предыдущая система JLayout
В предыдущей системе JLayout вызов вроде этого:
$layout = new JLayoutFile('joomla.content.tags');
$layout->render($itemTags);
Будет искать макет в:
[0] => templates/mytemplate/html/layouts
[1] => layouts
Здорово! Это значит, что я могу его переопределить. Но можно также принудительно указать папку, из которой вы хотите загружать макеты:
$layout = new JLayoutFile('joomla.content.tags', JPATH_SITE . '/components/com_mycomponent/layouts');
$layout->render($itemTags);
Этот код будет искать макеты в:
[0] => templates/mytemplate/html/layouts
[1] => components/com_mycomponent/layouts
Прекрасно! Макеты по-прежнему переопределяются!
Новые требования
В предыдущей системе шаблонизации у нас по-прежнему остались следующие проблемы:
- Разработчики, желающие использовать шаблонизацию внутри своих компонентов, должны указывать путь до макетов при каждом вызове или создавать собственные расширенные классы;
- Что будет, если верстальщик захочет, чтобы вывод тегов в представлении материала отличался от вывода в представлении категории?
- Если верстальщику нужно настроить отображение для одного конкретного компонента, как это сделать?
В своей работе я столкнулся с перечисленными выше проблемами и поэтому решил улучшить систему. Решение некоторых задач оказалось “крепким орешком”, т.к. в них использовалась старая система, но мне требовалась легкая автоматическая система, которая подходила бы для сложных решений.
Новые возможности
После моего первоначального предложения сообщество Joomla! отреагировало положительно и люди начали высказывать свои предложения. В результате получилась замечательная система, гораздо лучше той, которую я предложил изначально. В этом и заключается магия open source.
В качестве подсказки приведу пример того, как теперь можно вызывать макет:
$layout = new JLayoutFile('joomla.content.tags', null, array('debug' => true, 'client' => 1, 'component' => 'com_tags'));
1. Переопределение макета компонента
Теперь система автоматически ищет макеты в загруженном компоненте. Вызов, который мы использовали ранее:
$layout = new JLayoutFile('joomla.content.tags');
$layout->render($itemTags);
Будет автоматически искать макеты в следующих папках (в порядке очередности):
[0] => templates/mytemplate/html/layouts/com_mycomponent
[1] => components/com_mycomponent/layouts
[2] => templates/mytemplate/html/layouts
[3] => layouts
Это означает, что вы можете использовать стандартные макеты, переопределять их на уровне компонента и переопределять переопределение компонента на уровне шаблона. В нашем примере разработчик может управлять выводом разметки тегов в компоненте, а верстальщик может переопределять этот вывод тегов в компоненте на уровне шаблона.
2. Принудительное задание компонента
Предыдущий пример автоматически определяет компонент, из которого вызвана разметка. Но что будет, если мне нужно вывести теги по такому же принципу, как и в com_tags? Это можно сделать с помощью следующего вызова:
$layout = new JLayoutFile('joomla.content.tags', null, array('component' => 'com_tags'));
3. Принудительное задание клиентской части
Следующее нововведение - система может автоматически определять клиентскую часть. Это означает, что если вы находитесь во фронтэнде, система будет искать разметку для фронтэнда. Но я хочу вывести теги в администраторской части сайта точно также, как com_tags генерирует теги для фронтэнда! Вот пример того, как это делается:
$layout = new JLayoutFile('joomla.content.tags', null, array('client' => 1, 'component' => 'com_tags'));
Параметр клиентской части поддерживает следующие значения:
- 0, 'site' > frontend
- 1, 'admin' > backend
4. Добавление включаемых путей
Представим, что у вас имеется папка с макетами, но вы не хотите хранить все макеты в этой папке. Допустим, вам нужно добавить папку, в которой Joomla будет искать макеты, и в случае, если не найдет их, то загрузит стандартные. Например, у вас есть библиотека, включающая в себя собственные макеты для всех ваших компонентов. Тогда делаем такой вызов:
$layout = new JLayoutFile('joomla.content.tags');
$layout->addIncludePaths(JPATH_LIBRARIES . '/mylayouts');
Это добавит /libraries/mylayouts на верхний уровень при поиске макетов (максимальный приоритет). Мы также можем использовать массивы путей. Но помните, что в массиве последнее значение имеет самый высокий приоритет.
5. Суффиксы
Одним из предложений (в этом случае от Robert Deutz) было иметь возможность присваивать макетам суффиксы. Оригинальная идея заключалась в том, чтобы дать возможность расширениям искать характерный макет текущей версии Joomla! или использовать макет по умолчанию. Пример:
$layout = new JLayoutFile('joomla.content.tags', null, array('suffixes' => array('j3x', 'j25')));
echo $layout->render($this->item->tags->itemTags);
Файлом макета в данном случае будет /layouts/joomla/content/tags.j3x.php или /layouts/joomla/content/tags.j25.php. Но это только один из примеров применения. Представьте, что вам нужен макет для RTL языков. Вы можете добавить макет в поиск для постоянного мониторинга, не подключен ли активный RTL язык. Или представьте почтовый индекс в адресе покупателя, который отображается в разных местах / в разном формате в зависимости от страны. Можно добавить проверку определенного макета для страны покупателя.
6. Субмакеты
Одной из неприятных вещей, которые я нашел в
Давайте рассмотрим другой пример: в redCOMPONENT мы хотели использовать настраиваемые инвойсы. Я сразу же подумал о макетах. Вот так мог бы выглядеть глобальный вызов:
JLayoutHelper::render('invoice', $invoiceData);
А внутри макета что-то типа:
<div>
<div>
<?php echo $this->sublayout('shopper', $displayData['shopper']); ?>
</div>
<div>
<?php echo $this->sublayout('header', $displayData); ?>
</div>
<div>
<?php echo $this->sublayout('products', $displayData['products']); ?>
</div>
<div>
<?php echo $this->sublayout('footer', $displayData); ?>
</div>
</div>
Это главный макет, который вызывает субмакеты. Таким образом, пользователи могли бы переопределить шапку инвойса и не затрагивать остальную систему.
При вызове субмакета система пытается найти папку, названную так же, как и этот макет, с субмакетами внутри. В этом примере у нас был бы главный макет invoice.php и в этой же папке была бы папка под названием invoice, которая содержит в себе субмакеты (shopper.php, header.php, products.php & footer.php).
Субмакеты будут наследовать любые настройки, переданные в родительский макет. Они будут искать по тем же включаемым путям, в той же клиентской части и с теми же суффиксами.
7. Режим отладки
Когда вы начинаете иметь дело с макетами в разных компонентах, клиентах и включаемых путях, вы можете легко запутаться и до конца не понимать, откуда же система загружает макеты. Именно поэтому мы включили отладочную систему UBU (Useful But Ugly :D – полезную, но ужасную). Для её включения необходимо передать параметр debug
со значением true
:
$layout = new JLayoutFile('joomla.content.tags', null, array('suffixes' => array('j3x', 'j25'), 'debug' => true));
echo $layout->render($this->item->tags->itemTags);
Вы увидите что-то вроде этого:
Где не использовать макеты?
Макеты являются хорошей штукой, если их использовать по назначению, но если их использовать в неправильных местах, то это уже не то. Вот теперь все хотят перевести всё на макеты. Поэтому вы легко можете найти макеты, которые используются материалами, баннерами, контактами и т.д. Вы скажете: «Круто же, не? Мы не дублируем код!». Нет! Мы просто создаем один макет с кучей условий для различий между компонентами. По моему мнению, нет смысла использовать макет для отображения четырех полей. Это то, что должно быть сделано в шаблоне и никогда не использовать повторно вне ядра. И вот мой совет: если это может быть использовано вне ядра, тогда есть смысл делать макет. Пример таких макетов: отобразить список, кнопку, меню, поле, постраничную навигацию…Но в любом случае, макеты не панацея.
Итог
Макеты на самом деле являются мощным инструментом и вещью, которая поможет нам улучшить отношения между кодерами и верстальщиками. Есть много мест, где можно использовать макеты. Некоторые из них пока еще не исследованы, а некоторые просто ждут, пока кто-то сделает эту работу.