Реализация шаблонов на PHP

Просмотров: 6157Комментарии: 4
ПрограммированиеPHP-MySQL
Реализация шаблонов на PHP

Сегодня мы рассмотрим создание класса шаблона для своей CMS. Класс шаблонов это незаменимая часть любого сайта. Класс простой без использования кэширования. Принцип работы: загрузка шаблона, замена переменных в шаблоне и вывод шаблона.

Сегодня существует много мощных классов для работы с шаблонами, например такой тяжеловес как Smarty или другой подобный ему. Но для небольшого проекта можно использовать простой шаблонизатор на PHP.


Возможности:

1. Замена вставок {NAME} на заданный текст

2. Подключение шаблонов в шаблоне

3. Выделение блоков в шаблоне

...

данный код шаблона будет выведен только при использовании команды

set_block_vars('nameblock',array('var1' => 'text';));

При использовании в цикле можно выводить блок много раз.

Переменные в блоке должны быть вида {nameblock.NAME}


Создадим в корне сайта папку template для хранения шаблонов и папку includes, в этой папке создадим файл mytemplates.php.

Откроем его в Notepad++, и создаем класс

<?php
class Template
{
	//тут будет код класса
}
?>

В созданном классе объявим переменные:

var $file = ""; //для хранения имени файла шаблона
var $blocks = array(); 
var $vars = array(); //для хранения переменных шаблона
var $compiled = ""; //результат компиляции шаблона

Наш класс шаблонов будет состоять из 6 функций

set_file - выбор файла шаболона

set_vars - установка нескольких переменных

set_block_vars - установка переменных в определенном блоке

load_file - загрузка шаблона

compile - компилирование

display - вывод результата


И так функция выбора файла шаблона, тут ничего сложного

// Установка файла шаблона
function set_file($fname)
{
	//переменная root_path объявляется перед подключением шаблона
	global $root_path; //корень сайта
	$file = $root_path.'template/'.$fname.'.tpl'; //имя файла шаблона
	//проверка существования шаблона и права на чтения
	if(is_file($file) && is_readable($file))
	{
		$this->file = $file;
		return;
	}
	die('<b>Fatal Error:</b> не могу открыть файл шаблона '.$file);
}

Функция установки переменных, которые заменяются в шаблоне

//Установка основных переменных
function set_vars($vars)
{
	foreach($vars as $var => $val)
	{
		//Просто заносим в массив для последующей обработки
		$this->vars["{{$var}}"] = $val;
	}
}

Установка переменных для определенного блока.

Без вызова этой функции блок выделенный тегами в шаблоне не будет выводиться.


//Установка блочных переменных
function set_block_vars($block, $vars)
{
	//обрабатываем имя блока и устанавливаем переменные
	$block_arr = explode('.',$block);
	$c = &$this->blocks;
	$last = $block_arr[sizeof($block_arr)-1];
	foreach($block_arr as $r)
	{
		if(!isset($c['#blocks'][$r]) && $r != $last)
		{
			return false;
		}
		else if($r == $last)
		{
			$c['#blocks'][$r][] = array(
				'#vars'	=> array(),
				'#blocks'	=> array(),
			);
		}
		$c = &$c['#blocks'][$r][sizeof($c['#blocks'][$r])-1];
	}
	//Полученные переменные заносим в массив
	foreach($vars as $var => $val)
	{
		$c['#vars']["{{$var}}"] = $val;
	}
}

Функция загрузки шаблона

//Загрузка шаблона
function load_file($file)
{
	global $root_path;
	$c = file_get_contents($file); //загрузка файла в переменную
	$matches = array();
	//Поиск подключения внешних файлов шаблона
	preg_match_all('#<!-- INCLUDE ([^>]+) -->#', $c, $matches, PREG_SET_ORDER);
	$f = $r = array();
	//Если есть такие то загружаем
	foreach($matches as $inc)
	{
		if(!is_file($root_path."template/{$inc[1]}.tpl") || !is_readable($root_path."/template/{$inc[1]}.tpl"))
		{
			continue;
		}
		$f[] = $inc[0];
		$r[] = $this->load_file($root_path."template/{$inc[1]}.tpl");
	}
	$c = str_replace($f, $r, $c);
	return $c;
}

Функция вывода результата компиляции

//Вывод резултата
function display()
{
	$this->compile(); //компилируем
	eval($this->compiled); //и выводим
}

Последняя функция компилирования шаблона

// Компилирование шаблона
function compile()
{
	$c = $this->load_file($this->file); // загружаем файл шаблона с подфайлами
	// заменяем все определенные переменные в шаблоне
	$c = str_replace(array_keys($this->vars), array_values($this->vars), $c);
	$matches = array();
	//Поиск блоков в шаблоне
	preg_match_all('#<!-- BEGIN ([a-zA-Z._]+) -->#', $c, $matches, PREG_SET_ORDER);
	$indexes = array();
	$loops = array();
	$i = 0;
	//Обработка найденных блоков
	foreach($matches as $match)
	{
		$indexes[$match[1]] = "\$i_$i";
		$blocks = explode('.', $match[1]);
		$loop = "<?php for({$indexes[$match[1]]} = 0; {$indexes[$match[1]]} < sizeof(\$this->blocks['#blocks']['$blocks[0]']";
		for($j = 1; $j < sizeof($blocks); $j++)
		{
			$in = implode('.', array_slice($blocks, 0, $j));
			$loop .= "[{$indexes[$in]}]['#blocks']['{$blocks[$j]}']";
		}
		$loop .= "); {$indexes[$match[1]]}++){ ?>";
		$loops[$match[0]] = $loop;
		$i++;
	}
	//замена переменных в блоках
	$c = str_replace(array_keys($loops), array_values($loops), $c);
	$c = str_replace('<!-- END -->', '<?php } ?>', $c);
	
	//поиск переменных {}
	$matches = array();
	$vars = array();
	preg_match_all('#{([A-Za-z_]+\.[A-Za-z_.]+)}#', $c, $matches, PREG_SET_ORDER);
	foreach($matches as $match)
	{
		$blocks = explode('.', $match[1]);
		$var = "<?=(\$this->blocks";
		for($j = 0; $j < sizeof($blocks)-1; $j++)
		{
			$in = implode('.', array_slice($blocks, 0, $j+1));
			$var .= "['#blocks']['{$blocks[$j]}'][{$indexes[$in]}]";
		}
		$var .= "['#vars']['{{$blocks[$j]}}']) ?>";
		$vars[$match[0]] = $var;
		$i++;
	}
	
	$c = str_replace(array_keys($vars), array_values($vars), $c);
	$this->compiled = '?>'.$c;
}

Пример использования

<?php
$root_path = './';
$tmp = new Template();
$tmp -> set_file('index_body');
$tmp -> set_vars(array(
	'TITLE' => 'Мой сайт',
	'TEXT' => $text));
$tmp -> display();
?>

Пример шаблона

<!-- INCLUDE overall_header -->
<div id="menubox">
	<!-- INCLUDE left_menu -->
</div>
<div id="mainbox">
	<div class="boxHead">
		<div class="boxLeft">{TITLE}</div>
	</div>
	<div class="boxBody">
		<div class='boxLeft'>
			{TEXT}
		</div>
	</div>
	<div class='boxFooter'>
		<div class='boxLeft'> </div>
	</div>
</div>
<!-- INCLUDE overall_footer -->

Скачать класс шаблона

Комментариев: 4 RSS

1 sANYA 16-08-2012 00:53

Покажите, пожалуйста, пример использования set_block_vars

2 Admin 17-08-2012 12:06

В шаблоне

<!-- BEGIN team -->

{team.TRENER}

{team.COACH}

<!-- END -->

В коде

set_block_vars('team',array('TRENER' => 'text', 'COACH' => 'text';));

3 sANYA 17-08-2012 23:32

конечно главный минус подобного шаблонизатора что в шаблонах нельзя использовать элементарной логики

4 Владимир 22-11-2012 11:09

А логику серьёзно никак не реализовать?

Оставьте комментарий!

grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

     

  

Если вы уже зарегистрированы как комментатор или хотите зарегистрироваться, укажите пароль и свой действующий email. При регистрации на указанный адрес придет письмо с кодом активации и ссылкой на ваш персональный аккаунт, где вы сможете изменить свои данные, включая адрес сайта, ник, описание, контакты и т.д., а также подписку на новые комментарии.

(обязательно)