В этом уроке разбираемся с альтернативным подключением пользовательских шаблонов и подшаблонов (слоёв).
Есть в SMF полезная функция, WrapAction
(Themes.php), которая позволяет без всяких хуков подключать шаблоны, подшаблоны, языковые файлы, нужные функции в конкретных PHP-файлах.
Вот её код полностью:
/**
* Possibly the simplest and best example of how to use the template system.
* - allows the theme to take care of actions.
* - happens if $settings['catch_action'] is set and action isn't found
* in the action array.
* - can use a template, layers, sub_template, filename, and/or function.
*/
function WrapAction()
{
global $context, $settings;
// Load any necessary template(s)?
if (isset($settings['catch_action']['template']))
{
// Load both the template and language file. (but don't fret if the language file isn't there...)
loadTemplate($settings['catch_action']['template']);
loadLanguage($settings['catch_action']['template'], '', false);
}
// Any special layers?
if (isset($settings['catch_action']['layers']))
$context['template_layers'] = $settings['catch_action']['layers'];
// Any function to call?
if (isset($settings['catch_action']['function']))
{
$hook = $settings['catch_action']['function'];
if (!isset($settings['catch_action']['filename']))
$settings['catch_action']['filename'] = '';
add_integration_function('integrate_wrap_action', $hook, false, $settings['catch_action']['filename'], false);
call_integration_hook('integrate_wrap_action');
}
// And finally, the main sub template ;).
if (isset($settings['catch_action']['sub_template']))
$context['sub_template'] = $settings['catch_action']['sub_template'];
}
Дословный перевод комментария к функции:
Возможно, это самый простой и лучший пример использования системы шаблонов:
- позволяет теме позаботиться о действиях
- выполняется, если задан параметр
$settings['catch_action']
, а action не найден в массиве action- может использовать шаблон, слои, подшаблон, имя файла и/или функцию
Итак, по порядку, если у нас задана переменная $settings['catch_action']
(судя по коду, это должен быть массив), то при заходе на заданный экшен можно подгрузить определённые файлы и функции. Например, создадим файл Themes/default/Example.template.php
:
<?php
function template_test()
{
echo 'World!';
}
Далее, в вашем приложении (можно добавить, например, в конце функции template_init
файла index.template.php
темы оформления) определим следующий код:
global $context, $settings;
// Подключаем шаблон Example.template.php и вызываем функцию template_test внутри него
if (isset($context['current_action']) && $context['current_action'] === 'my_action')
$settings['catch_action'] = array(
'template' => 'Example',
'sub_template' => 'test',
'layers' => [],
);
Затем перейдем по адресу http://ваш_форум/?action=my_action
и увидим белую страницу с текстом World!
.
Чуть изменим код выше:
global $context, $settings;
// Вызываем функцию test(), подключаем шаблон Example.template.php и вызываем функцию template_test внутри него
if (isset($context['current_action']) && $context['current_action'] === 'my_action')
$settings['catch_action'] = array(
'template' => 'Example',
'function' => 'test',
'sub_template' => 'test',
'layers' => [],
);
И далее в коде определим функцию test
:
function test()
{
echo 'Hello ';
}
Обновим страницу и увидим текст Hello World!
. Если функция test
находится в другом файле, его также можно указать с помощью ключа 'filename' => 'file.php'
. Если нам нужно подключить не функцию, а метод внутри текущего класса, это указывается так:
global $context, $settings;
// Вызываем функцию test(), подключаем шаблон Example.template.php и вызываем функцию template_test внутри него
if (isset($context['current_action']) && $context['current_action'] === 'my_action')
$settings['catch_action'] = array(
'template' => 'Example',
'function' => __CLASS__ . '::test#', // уберите «решётку», если обращаетесь к статическому методу
'sub_template' => 'test',
'layers' => [],
);
Далее добавим в файле Example.template.php
ещё несколько функций:
function template_example_layer_above()
{
echo 'ВЕРХНИЙ СЛОЙ';
}
function template_example_layer_below()
{
echo 'НИЖНИЙ СЛОЙ';
}
Изменим код выше:
global $context, $settings;
// Вызываем функцию test(), подключаем шаблон Example.template.php и вызываем функцию template_test внутри него
if (isset($context['current_action']) && $context['current_action'] === 'my_action')
$settings['catch_action'] = array(
'template' => 'Example',
'function' => __CLASS__ . '::test#', // уберите «решётку», если обращаетесь к статическому методу
'sub_template' => 'test',
'layers' => ['html', 'body', 'example_layer']
);
Обновим страницу и увидим наш шаблон вместе со слоями. Последовательно уберите html
и body
из массива layers
и посмотрите на результат.
Кстати, визуально увидеть начало и конец каждого слоя в любом шаблоне можно, добавив к текущему адресу параметр debug
.
Если в коде выше убрать условие if (isset($context['current_action']) && $context['current_action'] === 'my_action')
, то выбранный нами шаблон будет подключаться при обращении к любому несуществующему экшену.
Также по коду функции WrapAction
можно заметить, что в конце вызова нашей пользовательской функции test
будет задействован и хук integrate_wrap_action
.
Больше примеров использования $settings['catch_action']
можно найти в файлах темы оформления Spirate
Итак, подытожим: шаблон - это файл вида XXX.template.php
, подшаблон - функция вида template_xxx
внутри файла шаблона, слои - парные функции вида template_xxx_above
(отображается НАД основным контентом) и template_xxx_below
(отображается ПОД основным контентом) в том же файле. Подробнее о слоях можно узнать в статье Изучаем слои.