Это не детальное описание, а лишь принципы работы. Все написанное относится к новой версии (2.6).
Шаблон представляет из себя фрагмент HTML-кода, котопый может содержать вставки.
Какой шаблон будет обрабатываться, задается программно. Шаблон передается в ф-ию обработки, который находит в нем вставки и подменяет их (текстовым) результатом работы ф-ии, привязанной к этому шаблону.
Работа ядра состоит из следующих этапов:
1. Определение класса-обработчика вызывамой страницы (по одному из переданных параметров) и передача управления ему.
2. По другому параметру запроса (подзапрос) выбирается ф-ия класса-обработчика для выполения соответствующих запросу действий (опционально). После выполняется код, общий для всех поззапросов.
3. Свойство
$templates ядра содержит иерархию шаблонов. Производится их обработка.
4. Если в обрабатываемом шаблоне обнаружена вставка, ищется соответствующая ей ф-ия (при необходимости динамически подгружаются модули). Если ф-ия найдена, управление передается ей, а возвращаемое значение вставляется на место вставки. Если ф-ия не найдена, то вставка остается неизменной.
Этап 1 позволяет иметь несколько обработчиков страниц от разных разработчиков.
Пример запроса:
http://my.site.com/index.php?p=lentaВызывается модуль ленты новостей.
Этап 2 позволяет не писать в каждом классе однотипный код - требуется лишь задать таблицу соответствия.
Пример:
http://my.site.com/index.php?p=lenta&s=addВызывается модуль ленты новостей, затем обработчик подзапроса "add" в нем.
Результат не обязательно линеен, т.к. можно обрабатывать остальные параметры (случай, когда новость отсылается из браузера на сайт), а если их нет - выбрать шаблон с формой.
Этап 3 - непосредственно обработка.
Этап 4 - подмена вставок. Вызванная ф-ия может, в свою очередь, передать на обработку еще один шаблон (или их набор). Т.е. переход к этапу 3.
Реальный пример.
Класс-обработчик lenta.php.
<?php
class Object_lenta extends Site
{
function Object_lenta(&$owner)
{
// задание таблицы подзапросов
$this->subpages += array(
'add' => 'lenta_add_message',
);
// инициализация класса-предка и обработка подзапросов
parent::Site($owner);
}
function init()
{
// входные параметры
$this->id = isset($_REQUEST['id']) ? $_REQUEST['id'] + 0 : 0;
$this->author = isset($_REQUEST['author']) ? $_REQUEST['author'] : '';
$this->title = isset($_REQUEST['title']) ? $_REQUEST['title'] : '';
$this->text = isset($_REQUEST['text']) ? $_REQUEST['text'] : '';
$this->description = isset($_REQUEST['des']) ? $_REQUEST['des'] : '';
// если класс - не обработчик страницы, а лишь донор ф-ий для вставок, то шаблонов не касаемся.
if ($this->owner === false)
{
$this->templates['start'][] = 'lenta_index_start';
$this->templates['end'][] = 'lenta_index_end';
$this->templates['sub'] = 'lenta_view';
}
parent::init();
}
function fin()
{
parent::fin();
}
/* ************************* */
function lenta_add_message()
{
if (!empty($this->author) && !empty($this->title) && !empty($this->text) &&
!empty($this->description))
{
// ........ обработка и запись в базу
$this->templates['sub'] = 'lenta_added';
$this->refresh(3, 'index.php?p=lenta');
}
else
$this->templates['sub'] = 'lenta_add';
}
/* ************************* */
function show_lenta_last()
{
// ........ выдача нескольких последних новостей
return $result;
}
function show_lenta_list()
{
// ........ выдача списка новостей
return $result;
}
function view_lenta_text()
{
if ($this->id == 0)
{
// ..... если номер новости не задан, будет выдана последняя
}
// ........ выдача новости
return $result;
}
function show_lenta_add_author_component()
{
return urlencode($this->author);
}
function show_lenta_add_title_component()
{
return urlencode($this->title);
}
function show_lenta_add_des()
{
return htmlspecialchars($this->description);
}
function show_lenta_add_text()
{
return htmlspecialchars($this->text);
}
}
?>
Перед созданием класса были заданны общие для сайта шаблоны - header и footer. Шаблон может переопределить их.
Шаблон header.html.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<meta name="description" content="Клуб программистов "Весельчак У" - программирование и общение" />
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="Pragma" content="no-cache" />
<meta name="copyright" content="(c) 2002-2007 Veselchak U" />
<meta name="author" content="Громозека" />
<meta name="modifier" content="Громозека, MOPO3, RXL" />
<meta name="webmoney.attestation.label" content="webmoney attestation label#BA136CB9-266D-4190-8CB5-02359A2A10B0" />
<meta name="keywords" content="club, клуб, veselchak u, весельчак у, programing, программирование, driver, драйвер, ddk, web, веб, php, perl, html, xml, js, javascript, dbf, databases, базы данных, mysql, oracle, interbase, c++, ansi c, vc++, visual, начинающим, for beginners, технологии разработки, uml, patterns, патерны, idef, ооп, java, c#, .net, delphi, vb, visual basic, vba, 1c, 1с, авторское по, embedded, net, network, сети, software, программы, games, игры, graphics, graphix, grafix, графика, articles, статьи, books, книги, files, файлы" />
<link rel="stylesheet" type="text/css" href="styles/main.css" media="screen" />
<link rel="stylesheet" type="text/css" href="styles/articles.css" media="screen" />
<title>[!SITE:PAGE_TITLE!]</title>
<link rel="alternate" type="application/rss+xml" title="Клуб программистов Весельчак У - RSS - Статьи" href="xml/articles.rss.xml" />
<link rel="alternate" type="application/rss+xml" title="Клуб программистов Весельчак У - RSS - Файлы и книги" href="xml/files.rss.xml" />
<link rel="alternate" type="application/rss+xml" title="Клуб программистов Весельчак У - RSS - Ссылки" href="xml/links.rss.xml" />
<link rel="alternate" type="application/rss+xml" title="Клуб программистов Весельчак У - RSS - В мире технологий" href="xml/blog.rss.xml" />
<script language="JavaScript" type="text/javascript" src="js/lib/utils.js"></script>
<script language="JavaScript" type="text/javascript" src="js/lib/menu.js"></script>
</head>
<body>
<table cellspacing="0" cellpadding="0" border="0" width="100%" class="main_layout">
<!-- header -->
<tr id="header_line">
<td rowspan="5">
<div id="overall_vertical_stick"></div>
</td>
<td>
<table cellspacing="0" cellpadding="0" width="100%" id="header">
<tr>
<td class="header_l"> </td>
<td class="header_m"> </td>
<td class="header_r">
<div style="font-weight: bold; font-size: 11px; text-align: right; float: right;">
<a href="index.php?p=admin" title="Вход в административную часть">Вход</a>
</div>[!SITE:STATISTICS!]</td>
</tr>
</table>
</td>
</tr>
<!-- menu -->
<tr id="menubar_t_line">
<td>
<table cellspacing="0" cellpadding="0" width="100%" id="menubar_t">
<tr>[!SITE:STATIC_MENU!]
</tr>
</table>
</td>
</tr>
<!-- body -->
<tr id="body_line"><td>
Шаблон footer.html.
</td></tr>
<!-- menu -->
<tr id="menubar_b_line">
<td>
<table cellspacing="0" cellpadding="0" width="100%" id="menubar_b">
<tr>[!SITE:STATIC_MENU!]
</tr>
</table>
</td>
</tr>
<!-- footer -->
<tr id="footer_line">
<td>
<div id="footer">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td class="footer_l" width="220">
© Copyright "Весельчак У" 2002-2007
</td>
<td class="footer_m">
Все права на статьи принадлежат указанным авторам или в противном случае сайту "Весельчак У".
Перепечатка статей без указания ссылок и без уведомления администрации сайта - запрещена!
</td>
<td class="footer_r" width="180">
Powered by [!SITE:VERSION!]<br />
<a href="http://dev.shelek.com/">http://dev.shelek.com</a>
</td>
</tr>
</table>
<!-- XHTML 1.0 and CSS validated -->
<a target="_blank" href="http://validator.w3.org/check?uri=[!SELF_URL_COMPONENT!]" rel="nofollow"><img style="border:0;width:88px;height:31px" src="http://www.w3.org/Icons/valid-xhtml10" alt="" title="Valid XHTML 1.0 Transitional" /></a>
<a target="_blank" href="http://jigsaw.w3.org/css-validator/validator?uri=[!SELF_URL_COMPONENT!];profile=css2" rel="nofollow"><img style="border:0;width:88px;height:31px" src="http://www.w3.org/Icons/valid-css2" alt="" title="Valid CSS2!" /></a>
<!-- mail.ru counter - club.shelek.com - рассылка -->
<a target="_blank" href="http://top.mail.ru/jump?from=1043901"><img src="http://dd.ce.bf.a0.top.list.ru/counter?id=1043901;t=210" border="0" height="31" width="88" alt="" title="Рейтинг@Mail.ru (рассылка)" /></a>
<!-- mail.ru counter - forum.shelek.com -->
<a target="_blank" href="http://top.mail.ru/jump?from=378937"><img src="http://top.list.ru/counter?js=na;id=378937;t=52" border="0" height="31" width="88" alt="" title="Рейтинг@Mail.ru (сайт)" /></a>
</div>
</td>
</tr>
</table>
<script language="JavaScript" type="text/javascript">//<![CDATA[
var isIE = (navigator.appName.indexOf('Internet Explorer') != -1);
var isOpera = (navigator.appName.indexOf('Opera') != -1);
var isGecko = (navigator.appName.indexOf('Gecko') != -1);
function arrange_layout(first)
{
if (!first && !window.innerHeight)
location.reload();
var screen_height = window.innerHeight ? window.innerHeight : document.body.clientHeight;
document.getElementById('overall_vertical_stick').style.height = screen_height + 'px';
var body_height = screen_height
- document.getElementById('header').clientHeight
- document.getElementById('menubar_t').clientHeight
- document.getElementById('menubar_b').clientHeight
- document.getElementById('footer').clientHeight - 20;
if (isIE || isOpera)
document.getElementById('body_line').style.height = body_height + 'px';
}
arrange_layout(true);
window.onresize = arrange_layout;
//]]></script>
<script language="JavaScript" type="text/javascript" src="js/menu.php"></script>
</body>
</html>
Код класса добавляет шаблоны lenta_index_start и lenta_index_end.
Шаблон lenta_index_start.html.
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr><td id="column_l">
<!-- column 1 -->
<!-- lenta catalog -->
<div class="box">
<div class="box_title_icon"><div class="box_title">В мире технологий</div></div>
<div class="box_content">
[!LENTA:LIST!]
</div>
</div>
<!-- reclame -->
<div class="box">
<div class="box_title_icon"><div class="box_title">Реклама</div></div>
<div class="box_content">
[!RECLAME:LINKS2!]
</div>
</div>
</td>
<td id="column_mr">
<!-- column 2 -->
Шаблон lenta_index_end.html.
</td></tr>
</table>
В зависисмости от параметров в середину добавляется еще один шаблон.
Шаблон lenta_view.html.
<!-- lenta text -->
<div class="box">
<div class="box_title_icon"><div class="box_title">Сообщение</div></div>
<div class="box_content">
[!LENTA:TEXT!]
</div>
</div>
Шаблон lenta_add.html.
<!-- info -->
<div class="box">
<div class="box_title_icon"><div class="box_title">Внимание</div></div>
<div class="box_content">
<div class="box_item help">
Все сообщения попадают на премодерацию! Для того, что бы они появились в ленте модератор сайта должен подтвердить ввод сообщения.
</div>
</div>
</div>
<!-- add message form -->
<div class="box">
<div class="box_title_icon"><div class="box_title">Ваше сообщение</div></div>
<div class="box_content">
<div class="box_item blog_form">
<form action="index.php?p=lenta&s=add" method="post">
<label>Кто написал:</label>
<input type="text" name="author" size="80" value="[!LENTA:ADD_AUTHOR_COMPONENT!]" />
<br />
<label>Заголовок:</label>
<input type="text" name="title" size="80" value="[!LENTA:ADD_TITLE_COMPONENT!]" />
<br />
<label>Текст краткого описания:</label>
<textarea name="des" rows="4" cols="60">[!LENTA:ADD_DES!]</textarea>
<br />
<label>Текст новости:</label>
<textarea name="text" rows="20" cols="60">[!LENTA:ADD_TEXT!]</textarea>
<br />
<input type="submit" value="Послать" />
<input type="reset" value="Стереть" />
</form>
</div>
</div>
</div>
Шаблон lenta_added.html.
<!-- info -->
<div class="box">
<div class="box_title_icon"><div class="box_title">Внимание</div></div>
<div class="box_content">
<div class="box_item help">
<br />
Ваше сообщение добавлено в очередь. После проверки модератором оно попадет в ленту новостей.<br />
<br />
</div>
</div>
</div>
Таблица подмен для модуля lenta.
'LENTA:LAST' => 'show_lenta_last',
'LENTA:LIST' => 'show_lenta_list',
'LENTA:TEXT' => 'view_lenta_text',
'LENTA:ADD_AUTHOR_COMPONENT' => 'show_lenta_add_author_component',
'LENTA:ADD_TITLE_COMPONENT' => 'show_lenta_add_title_component',
'LENTA:ADD_DES' => 'show_lenta_add_des',
'LENTA:ADD_TEXT' => 'show_lenta_add_text',