По следам хабратопика Наследование шаблонов в Smarty хочу рассказать как около полутора лет назад я решил подобную задачу. В оличие от marazmiki с Django я знаком не был (хотя сейчас занимаюсь изучением именно его). Но крайне поверхностно был знаком с механизмом Master Pages из ASP.NET. Механизм заключается в том, что у нас есть практически полноценная страница, у которой отсутствует только блок с основным контентом.
Немного прикинув придумалось решение через стандарные функции Smarty и механизм наследования в PHP.
Прежде всего шаблон смарти:
Основные элементы на которые стоит обратить внимание это:
1. Main title{if $ADDITIONAL_TITLE} | {$ADDITIONAL_TITLE}{/if}
2. {include file=$__file_to_display}
Далее идет код, который со всем этим работает. Прежде всего, для применения настроек смарти и работы с данными общими для всего сайта у меня был создан абстракный класс, который наследовался напряму от Smarty:
Тут стоит упомянуть что структура хранения шаблонов в проекте имела следующий вид:
А шаблон приведенный выше является common_page.tpl (упрощенный меташаблона для пользовательских страниц).
Для каждого типа страниц существует свой наследник расширенного класса смарти, который занимался передачей в шаблон каких-то дополнительных данных. В частности наследник для common_page.tpl выглядит таким образом:
Тут в шаблон отдаются какие-то общие данные и дополнительный заголовок, если требуется, все как обычно. А далее мы переопределяем метод fetch базового класса Smarty так, чтобы он не компилировал отданный ему шаблон, а вставлял его в меташлаблон, и отдаем на компиляцию уже меташаблон со вставленным блоком данных.
В простейшем виде использование такой структуры кода сводится к следующему:
Написав 1 основной шаблон и создав небольшую цепочку наслования в пхп-коде получили возможность наследования шаблона смарти для однотипных страниц. Для введения дополнительных блоков на страницы наследников смарти придется немного усложнить, но это не очень трудоемкая и сложная задача.
Готов выслушать критику в свой адрес по поводу данного спооба наследования шаблонов в смарти.
Немного прикинув придумалось решение через стандарные функции Smarty и механизм наследования в PHP.
Прежде всего шаблон смарти:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" «www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd»>
<html xmlns=«www.w3.org/1999/xhtml»>
<head>
<title>Main title{if i$ADDITIONAL_TITLE} | {$ADDITIONAL_TITLE}{/if}</title>
<base href="{$ROOT_URL}" />
<meta http-equiv=«Content-Type» content=«text/html; charset=UTF-8» />
</head>
<body>
<div id=«base_div»>
<div id=«header_logo_div»>{include file=«header_logo.tpl»}</div>
<div>
<div id=«user_login_info»>{include file=«users/user_login_info.tpl»}</div>
<div id=«lang_selector»>{include file=«lang/selector.tpl»}</div>
</div>
<div>
<div id=«main_block»>
{include file=$__file_to_display}
</div>
</div>
</div>
* This source code was highlighted with Source Code Highlighter.
Основные элементы на которые стоит обратить внимание это:
1. Main title{if $ADDITIONAL_TITLE} | {$ADDITIONAL_TITLE}{/if}
2. {include file=$__file_to_display}
Далее идет код, который со всем этим работает. Прежде всего, для применения настроек смарти и работы с данными общими для всего сайта у меня был создан абстракный класс, который наследовался напряму от Smarty:
<?php
abstract class smarty_page_ex extends Smarty {
protected $module;
protected $action;
public function __construct($module = "", $action = "", smarty_config_wrapper $config = null) {
parent::Smarty();
$this->module = $module;
$this->action = $action;
$gconfig = global_config::get_instance();
if ($config === null) $config = $gconfig->get_smarty_config();
$this->compile_check = $config->get_tpl_compile_check();
$this->debugging = $config->get_smarty_debug();
$this->compile_dir = $config->get_tpl_compiled_path();
$this->cache_dir = $config->get_tpl_cache_path();
$this->template_dir = $config->get_tpl_path();
$this->config_dir = $config->get_tpl_config_path();
$lang = lang::get_instance();
$this->assign_by_ref("lang", $lang);
$this->assign("ROOT_URL", $gconfig->root_url);
$this->assign("MODULE", $module);
$this->assign("ACTION", $action);
$this->register_object("smarty_page_ex", $this);
}
/**
* Gets template full path
*
* @param string $base_path
* @return string
*/
protected function get_full_path() {
return (strlen($this->module) > 0 ? ($this->module . "/") : "");
}
}
?>
Тут стоит упомянуть что структура хранения шаблонов в проекте имела следующий вид:
<templates-dir>/
|-<module>
| |-<action>.tpl
|-home
| |-index.tpl
|-common_page.tpl
|-admin_page.tpl
|-mail_page.tpl
А шаблон приведенный выше является common_page.tpl (упрощенный меташаблона для пользовательских страниц).
Для каждого типа страниц существует свой наследник расширенного класса смарти, который занимался передачей в шаблон каких-то дополнительных данных. В частности наследник для common_page.tpl выглядит таким образом:
<?php
class common_page extends smarty_page_ex {
public function __construct($module = "", $action = "", $title = "", smarty_config_wrapper $config = null) {
parent::__construct($module, $action, $config);
$options = options::get_instance();
$this->assign_by_ref("options", $options);
$auth_user = auth_user::get_instance();
$this->assign_by_ref("auth_user", $auth_user);
$gconfig = global_config::get_instance();
$this->assign_by_ref("gconfig", $gconfig);
$lang = new languages();
$lang_list = db_adapter::get_instance()->get_list($lang);
$this->assign_by_ref("__languages", $lang_list);
$this->assign("ADDITIONAL_TITLE", $title);
}
/**
* Executes & returns or displays the template results
*
* @param string $template
* @param string $cache_id
* @param string $compile_id
* @param boolean $display
*/
public function fetch($template, $cache_id = null, $compile_id = null, $display = false) {
$this->assign("__file_to_display", $this->get_full_path() . $template);
return parent::fetch("common_page.tpl", $cache_id, $compile_id, $display);
}
}
?>
Тут в шаблон отдаются какие-то общие данные и дополнительный заголовок, если требуется, все как обычно. А далее мы переопределяем метод fetch базового класса Smarty так, чтобы он не компилировал отданный ему шаблон, а вставлял его в меташлаблон, и отдаем на компиляцию уже меташаблон со вставленным блоком данных.
В простейшем виде использование такой структуры кода сводится к следующему:
<?php
$tpl = new common_page("home", "index", "Welcome!");
$tpl->display();
?>
Написав 1 основной шаблон и создав небольшую цепочку наслования в пхп-коде получили возможность наследования шаблона смарти для однотипных страниц. Для введения дополнительных блоков на страницы наследников смарти придется немного усложнить, но это не очень трудоемкая и сложная задача.
Готов выслушать критику в свой адрес по поводу данного спооба наследования шаблонов в смарти.