<!– BEGIN:index –>
<table cellpadding="3">
<!– BEGIN:line –>
<!– BEGIN:names –>
<tr>
<!– BEGIN:name –>
<td><b>{team.name}</b></td>
<!– END:name –>
</tr>
<!– END:names –>
<!– BEGIN:cities –>
<tr>
<!– BEGIN:city –>
<td>{team.city}<br><br></td>
<!– END:city –>
</tr>
<!– END:cities –>
<!– END:line –>
</table>
<!– END:index –>
Этот шаблон парсится в цикле, в котором, в частности, используется условие
if (++$j == sizeof($teams) || ++$i == 3)
Так вот: 1) откуда берётся это волшебное число - "3"? 2) Наименования 'city' и 'name' должны быть указаны в трёх местах: в массиве данных, в шаблоне и в цикле обработки массива; последнее - лишняя слабость. Есть и ещё мелочь: в HTML не бывает таблиц с разным количеством ячеек в первой и последней строке (во всяком случае, без использования атрибутов 'rowspan'), а в данном примере работы XTemplate создаётся именно такая, "кривая" таблица.
***
Шаблон - это то, что придумал верстальщик. А он придумал таблицу в три колонки (произвол) и в две строки (семантика) - эти условия и должны отражаться в шаблоне, это и есть в данном случае минимальный и неделимый блок:
<tr><td><b>Спартак</b></td><td><b>Зенит</b></td><td><b>Шинник</b></td></tr>
<tr><td>Москва</td><td>Санкт-Петербург</td><td>Ярославль</td></tr>
Я чаще всего использую в качестве шаблонов функции. Это получилась довольно интересная задача - сделать функцию-шаблон для такой структуры - из "перпендикулярного" шаблону массива (с неизвестным заранее количеством строк):
$teams = Array(
Array('name' => 'Спартак', 'city' => 'Москва'),
Array('name' => 'Зенит', 'city' => 'Санкт-Петербург'),
Array('name' => 'Шинник', 'city' => 'Ярославль'),
Array('name' => 'Сатурн', 'city' => 'Раменское'),
Array('name' => 'Луч', 'city' => 'Владивосток')
);
Функция получилась такая:
function tpl_row_transpose($arr = array()) {
$res = '';
while (count($arr)) {
$name = array(1 => '', 2 => '', 3 => '');
$city = $name;
for($i = 1; $i <= count($name); $i ++) {
if ($team = array_shift($arr)) {
$name[$i] = $team['name'];
$city[$i] = $team['city'];
}
}
$res .= <<<TPL
<tr><td><b>$name[1]</b></td><td><b>$name[2]</b></td><td><b>$name[3]</b></td></tr>
<tr><td>$city[1]</td><td>$city[2]</td><td>$city[3]</td></tr>
TPL;
}
return $res;
}
Эта функция, конечно не универсальна (в отличие от блочных шаблонов XTemplate). Но ведь и 1) данная задача верстки довольно необычна (логично, что для нестандартной задачи нужна отдельная функция), 2) появление загадочного числа "три" значительно демистифицируется.
При расширении таблицы до 4-х колонок (ключевая проверка!) надо совершить больше действий, чем для XTemplate: надо изменить шаблон, добавив в него $name[4] и $city[4], а также добавить в массив $name элемент "4 => ''". Но эти действия достаточно логичны и наглядны; к тому же, развивая их логику, функцию можно улучшить. Например, вынести собственно шаблон в отдельный файл (сейчас, для простоты, в переменную) по "классической" схеме:
$tpl = "<tr><td><b>[name]</b></td><td><b>[name]</b></td><td><b>[name]</b></td></tr>
<tr><td>[city]</td><td>[city]</td><td>[city]</td></tr>";
Функции в этом случае понадобится уже две (да и, по-хорошему, чтобы избежать всяких global, вообще нужно делать класс):
function tpl_row_transpose2($arr = array(array('', '')), $tpl = '') {
global $magic_number, $counter;
$names = array_keys($arr[0]);
if (!preg_match_all("/\[{$names[0]}\]/", $tpl, $values)) return 'false';
$magic_number = count($values[0]);
foreach($names as $value) {
$counter = 0;
$tpl = preg_replace_callback("/\[({$value})\]/", 'tpl2func', $tpl);
}
$tpl = '$curr_tpl = "' . $tpl . '";';
$res = ''; $limit = 0;
while (count($arr)) {
for($i = 0; $i < $magic_number; $i ++) {
if ($row = array_shift($arr))
foreach($names as $value) ${$value}[$i] = $row[$value];
else foreach($names as $value) ${$value}[$i] = '';
}
eval($tpl);
$res .= $curr_tpl;
}
return $res;
}
function tpl2func ($matches){
global $counter;
return '$' . $matches[1] . '[' . $counter ++ . ']';
}
Это, типа, намного сложнее, чем "внешний" код обработки шаблона в XTemplate. Но ведь 1) там есть ещё и внутренний код (в подключаемом файле); 2) в системе XTemplate надо указывать сущности 'city' и 'name' в трёх местах, а функция tpl_row_transpose2 не требует таких подробностей (сущности должны коррелировать между собой только "напрямую" - в массиве и в шаблоне); 3) $magic_number "3" вычисляется без участия человека (на основе шаблона).
Результат работы обеих функций можно посмотреть на стр. http://ir2.ru/wysiwyg/complex_template.php (php код файла - по той же ссылке с ?code).