evg

Применение темплейтов, при создании сайтов на PHP.


Технология темплейтов (или по-русски "шаблоны") сейчас используется очень широко. Например в всяческих CMS (системах управления сайтом), форумах и прочих интернет-приложениях.

Смысл технологии довольно прост. Он заключается в разделении дизайна и логики работы (php - кода). Получаем красивый структуированный код. И отделенный от кода дизайн странички. В "дизайне" определяются пользовательские определения, заполняемые в "коде". На выходе получаем динамически сгенерированные странички.

Существут большое количество темплейтеров (систем управления темплейтами).
FastTemplate
/*
Был очень популярен.
Правда о нем написали:
If you need a PHP Template Engine then please, use SMARTY. FastTemplate was good when I first wrote it 
(not great though, since there are at least two places in the code where I’m wasting huge numbers of cycles) 
but Smarty is a lot… smarter. More importantly it’s updated fairly often.
*/
Cached Fast Template
PowerTemplate
PHemplate
XTemplate
И самое главное супер пупер мощный и развитой :)
Smarty
/*
Очень мощная система управления шаблонами с развитым внутренним языком. 
Имеет возможность компилировать шаблоны в php-скрипт, который впоследствии будет выполняться много быстрее.
Сейчас содержит много очень интересных дополнений:
Smarty: The PHP compiling template engine. 
Smarty Forums: The discussion forums for Smarty. 
SmartyValidate: A form validation class for the Smarty template language. 
SmartyFormtool: A javascript form tool class for the Smarty template language. 
SmartyPaginate: A pagination class for the Smarty template language. 
SmartyMenu: A dropdown menu class for the Smarty template language. 
TinyMVC An extremely compact MVC development framework for PHP. 
SafeSQL: A PHP class for automating the task of making SQL queries safe for use. 
Snoopy: A PHP class for simulating a web browser. 
Date_Calc: A PHP class for manipulating and calculating calendar dates. 
pmatch: A PHP grep-like command line utility with enhancements 
ContentFeeder: A PHP content feed assembling library (create RSS 2.0 feeds.) 
XMLParser: Parse XML documents into PHP arrays. Also comes with RSSParser, an extension 
			of XMLParser that creates simple RSS-specific array structures from RSS feeds. 
GoogleMapAPI A fully functional Google Map API for PHP. 
Easy Reflections Helped make some improvements to alpha blending and caching. 
Online CSS Compressor Efficiently compress CSS. 
str2img: View strings on an image. 
Basecamp PHP API: a PHP library wrapper for the Basecamp REST API. 
*/

Их много и все они чем-то хороши.
Но иногда полезно написать свой, благо ничего сложного в этом нет.

Самый простой темплейтер получает на вход массив элементов ключ => значение.
Затем делает перебор полученного массива заменяя все найденные ключи на их значения. И в конечном этапе производит вывод текста темплейта с замененными ключами.

Когда-то я написал подобный темплейтер, т.к. использовать готовый, мне не позволяла религия. :) Т.е. для общего развития.
Мне был необходим следующий функционал:
  • Замена ключей на значения.
  • Замена массива массивов ключей, для организации вывода однотипных блоков информации (например сообщений на форуме, гостевой книге и т.д.).
  • А также такая особенность как выполнение в теле темплейта встроенных в них php скриптов.
       Таким способом можно сделать темплейтер другого типа, в котором
    нет необходимости в замене ключей на значения, а для входного массива 
    используется php-функция explode, обеспечивающая преобразования массива 
    в php-переменные. Они уже автоматически заменятся на свои значения. Т.е. 
    переменные вписываются в тело шаблона в виде <? =$var ?>. 
    Сам шаблон выводится при помощи require "template.htm"

Реализовывать будем с применением ООП.
Организуем класс TEMPL.
Конструктор TEMPL() принимает имя файла темплейта и инициализирует переменные.
В качестве начала и конца ключа выберем <$ и $> соответственно. Они записываются в $BC и $EC. При необходимости можно перенастроить.
Флаг Prepared - флаг подготовки к выводу на экран. Не особо нужная вещь :) Но как-то прижилась.
Два ассоциативных массива $AA и $AAA для одномерного и многомерного массива значений.
В классе 8 методов:
LoadДля загрузки файла используется метод Load() он загружает файл в переменную $T.
SetValue установка значения массива, в аргументе массив ключ => значение
SetValueAустановка значения многомерного массива, в аргументе многомерный массив
AddValдобавляет пару ключ значение в массив $AA, в аргументах ключ и значение
AddValAдобавляет одномерный массив в $AAA, в аргументе массив
Prepareподготовка темплейта к выводу на экран, используется $AA
PrepareAподготовка темплейта к выводу на экран, используется $AAA
Outпроизводит подготовку к выводу, если еще не подготовленно и собственно вывод (т.е. не вывод, а возврат строки). В Out также предусмотренна возможность исполнения внутришаблонных php-скриптов. Делается при помощи eval. Да не безопасно, но работает. И для моего применения не особо важно.eval выполняется внутри блока ob_start(); ... ob_end_clean();. Все что выводится внутри этого блока попадает в переменную $out = ob_get_contents(); которую мы и возвращаем.



ob_start();
eval("?>".$this->O."<?");
$out = ob_get_contents();
ob_end_clean();	

Вот собственно код: Скачать Код класса TEMPL
+
-

<?php
/*
TEMPLATE class
evg_n@mail.ru
http://uggway.ru
*/
class TEMPL{
	var $fname; //template file
	var $AA; //associative array
	var $AAA; //array of associative array
	var $T;
	var $O;
	var $Prepared; 
	var $BC; 
	var $EC;

	function TEMPL($fname)
	{
		$this->fname = $fname;
		$this->BC="<$";
		$this->EC="$>";
		$this->AA=array();
		$this->AAA=array();
		
		$this->Load();
		$this->Prepared=FALSE;
	}
	
	
	function Load()
	{
		if(file_exists($this->fname)){	
			$this->T=file($this->fname);
		}	
	}

	function SetValue($vals)//array of values
	{
		$this->AA = array();
		foreach($vals as $vk =>$vv){
			$this->AA[$this->BC.$vk.$this->EC]=$vv;
		}		
		$this->Prepared=FALSE;
		
	}
	function SetValueA($vala)
	{
		$this->AA = array();
		$this->AAA = $vala;		
	}

	function AddVal($var,$val)
	{	
		$this->AA[$this->BC.$var.$this->EC] = $val;
	}
	
	function AddValA($val)
	{
		$this->AAA[] = $val;
	}
	
	function Prepare()
	{	
		if($this->T){		
			$v = join("", $this->T);					
			if(count($this->AA) > 0)
				$this->O = strtr($v, $this->AA);				
			else $this->O = $v;
			
			$this->Prepared = TRUE;
		}
	}
	
	function PrepareA()
	{	
		if($this->T){		
			$v = join("",$this->T);					
			$ret = "";
			if(count($this->AAA)>0){
				foreach($this->AAA as $i){
					$this->SetValue($i);
					if(count($this->AA)>0)
						$ret .= strtr($v,$this->AA);				
					else $ret .= $v;
				}
			}
			else 
				$ret = $v;
			$this->O = $ret;
			$this->Prepared = TRUE;
		}
	}
	
	function Out()
	{
		
		if($this->Prepared == FALSE)
		{
			if(count($this->AAA) > 0) $this->PrepareA();					
			else 
			$this->Prepare();
		}
			
		if($this->Prepared == FALSE) return "";	
		ob_start();
        eval("?>".$this->O."<?");
        $out = ob_get_contents();
        ob_end_clean();		
		return $out;
	}

}
?>


Рассмотрим применение данного шаблонизатора для генерации меню:

index.tmpl Текст indexf.php
+
-

<html>
<head>
<title><$title$></title>
<style>
	#wrap {width:500px; border:1px solid gray;}
	#menu {border:1px solid gray;}
	#bodym {height:400px;}
	#footer {border:1px solid gray;height:20px;}
	.menuelt { border:1px solid black;padding:10px;float:left;}
	.clearb {clear:both;}
</style>
</head>
	<body>
	<center>
	<div id='wrap'>
	<div id='menu'>
	<?
		//load menu
		$menu = new TEMPL("menu.tmpl");
		$menuarray = <$menu$>; //<-- this replacing
		foreach($menuarray as $i) {
			$menu->AddValA($i);
		}
		echo $menu->Out();
	?>
	<div class='clearb'></div>
	</div>
	<div id='bodym'> <$bodymessage$> </div>
	<div id='footer'> <$footer$> </div>
	</center>
</body>
</html>


menu.tmpl Текст menu.tmpl
+
-

<div class='menuelt'><a href='<$url$>'><$name$></a></div>


indexf.php Текст indexf.php
+
-

<?php
include_once "templ.php";
$ma = "array(
		array('name'=>'menu1', 'url' => 'url.html'),
		array('name'=>'menu2', 'url' => 'url2.html'),
		array('name'=>'menu3', 'url' => 'url3.html')
		)
		";
$index_t = new TEMPL("index.tmpl");
$index_t->AddVal("menu", $ma);
$index_t->AddVal("title", "Title");
$index_t->AddVal("bodymessage", "Body message :)");
$index_t->AddVal("footer", "evg 27.02.2011");
echo $index_t->Out();
?>


После всех манипуляций у нас получится вот такая вот страничка: Открыть в новом окне Полученная страничка
+
-

Скачать всё
Скачать templ.php

Коментарии