Раз уж все выкладывают, то и я выложу шаблонизатор: PHP: <?php /** * * @package Template * @version $Id: template.php,v 0.2 Exp $ * @copyright (c) kostyl * @license freeware * */ class TemplateException extends Exception {} /** *AbstractTemplate *абстрактный слой шаблонизатора */ abstract class AbstractTemplate { /** *Добавляет переменную парсинга *@param $name имя переменной в шаблоне *@param $value значение переменной в скрипте */ abstract function AddVar($name, $value); /** *Возвращает контент страницы *@param $file файл шаблона */ abstract function Prepare($file = NULL); /** *Выводит в браузер контент страницы */ abstract function Display(); /** *Устанавливает режим кэширования *@param $Cache объект AbstractTemplateCache для кэширования либо NULL по умолчанию */ abstract function SetCacheMode(AbstractTemplateCache $Cache = NULL); /** *Возвращает TRUE если кэширование используется */ abstract function GetCacheMode(); /** *Возвращает TRUE елси включено кэширование и кэш-файл актуальный */ abstract function IsCached(); } /** *AbstractTemplateCache *абстрактный словй кэша шаблонизатора */ abstract class AbstractTemplateCache { /** *Проверяет есть ли кэш-файл готовый к использованию */ abstract function IsActual(); /** *Читает кэш-файл и возвращает его контент */ abstract function Read(); /** *Сохраняте кэш-файл *@param $content кэш-контент */ abstract function Write($content); } /** *TemplateCache extends AbstractTemplateCache *кэширует шаблон по mtime !!! */ class TemplateCache extends AbstractTemplateCache { protected $_id; protected $_expired; /** *Конструктор *@param $cache_id кэш-файл *@param $expired время молодости кэш-файла */ function __construct($cache_id, $expired) { $this->_id = $cache_id; $this->_expired = $expired; } /** *Проверяет актуален ли кэш-файл */ function IsActual() { clearstatcache(); if (!($this->_id)) { return FALSE; } if (!file_exists($this->_id)) { return FALSE; } if (!($create_time = filemtime($this->_id))) { return FALSE; } if (($create_time + $this->_expired) < time()) { @unlink($this->_id); return FALSE; } return TRUE; } /** *Читает с диска и возвращает кэш-файл */ function Read() { if($this->IsActual()) { return @file_get_contents($this->_id); } return FALSE; } /** *Пишет на диск кэш-файл */ function Write($content) { if($this->_id) { return @file_put_contents($this->_id, $content); } } /** *Удаляет кэш файл */ function Delete() { clearstatcache(); if (file_exists($this->_id)) { @unlink($this->_id); } } /** *Удаляет группу кэш файлов в директории $cache_dir имена которых содержат $filename_mach *@param $cache_dir *@param $filename_mach */ static function DeleteCache($cache_dir, $filename_mach) { if ($handle = @opendir($cache_dir)) { while (($file = readdir($handle)) !== FALSE ) { if(preg_match('/'. $filename_mach . '/', $file)) { unlink($cache_dir . $file); } } closedir($handle); } } } /* *NaitiveParsingTemplate extends AbstractTemplate *инклудит шаблон для найтивного парсинга *использует буферизацию вывода естественно */ class NaitiveParsingTemplate extends AbstractTemplate { protected $_vars = array(); protected $_file; protected $_Cache = NULL; /** *Конструктор *@param $file файл шаблона */ function __construct($file = NULL) { $this->_file = $file; } /** *Добавляет переменную парсинга *@param $name имя переменной в шаблоне *@param $value значение переменной в скрипте */ function AddVar($name, $value) { $this->_vars[$name] = ($value instanceof AbstractTemplate) ? $value->Prepare() : $value; } /** *Парсит шаблон возвращая контент *@param $file файл шаблона */ protected function Parse($file = NULL) { if ($file) { $this->_file = $file; } if (!$this->_file) { throw new TemplateException(__CLASS__ . '::Parse()=>Template file is not set'); } $varcount = extract($this->_vars); if ($varcount !== count($this->_vars)) { throw new TemplateException(__CLASS__ . '::Parse()=>Extract vars error ' . $varcount . '<>' . count($this->_vars)); } ob_start(); if(!file_exists($this->_file)) { throw new TemplateException(__CLASS__ . '::Parse()=>Tamplate is not found'); } include($this->_file); return ob_get_clean(); } /** *Возвращает контент страницы *@param $file файл шаблона */ function Prepare($file = NULL) { if ($this->GetCacheMode()) { if ($this->_Cache->IsActual()) { return $this->_Cache->Read(); } else { $content = $this->Parse($file); $this->_Cache->Write($content); return $content; } } else { return $this->Parse($file); } } /** *Выводит в браузер контент страницы */ function Display() { header('Expires: 0'); header('Pragma: no-cache'); header('Cache-Control: no-cache, no-store, max-age=0, s-maxage=0, must-revalidate'); echo $this->Prepare(); } /** *Устанавливает режим кэширования *@param $Cache объект AbstractTemplateCache для кэширования либо NULL по умолчанию */ function SetCacheMode(AbstractTemplateCache $Cache = NULL) { $this->_Cache = $Cache; } /** *Возвращает TRUE если кэширование используется */ function GetCacheMode() { if(is_object($this->_Cache)) { return TRUE; } return FALSE; } /** *Возвращает TRUE елси включено кэширование и кэш-файл актуальный */ function IsCached() { if ($this->GetCacheMode()) { return $this->_Cache->IsActual(); } return FALSE; } } /** *Абстрагируемся */ final class Template extends NaitiveParsingTemplate {} Пример для профиля пользователя, допустим: PHP: <?php $TplUserPorfile = new Template('profile.html'); $TplUserPorfile->SetCacheMode(new TemplateCache('./cache/profile' . md5($_GET['userid']) . '.ch', 60*60*24*31)); if(!$TplUserPorfile->IsCached()) { $TplUserPorfile->AddVar('L_NAME', getUserName($_GET['userid'])); $TplUserPorfile->AddVar('L_EMAIL', getUserEmail($_GET['userid'])); } $TplUserPorfile->Display(); Ну и в profile.html должно быть написано: PHP: <?php echo $L_NAME?> <?php echo $L_EMAIL?> Если надо удалить кэшь: PHP: <?php TemplateCache::DeleteCache('./cache/profile' . md5($_GET['userid']) ); Вот такие блины с котятами.
вот такое не одобряю а если у меня за раз в 2 местах используется этот шаблон но с разными зачениями? что 2 раза делать include или file_get_contents кеширование кстати при натив пхп используется редко имхо... так же несколько раз создавать один и тот же объект, ну имхо - не комильфо такой запись выглядит немного...мм, странно
Это подход, который называют OOP ради OOP. Реально нужен один класс шаблонизатора и всё. Остальное - излишки.
Хм. Ну вообще она кросс, да. Но просто я не люблю сваливать много кода в один класс, и предпочитаю правильное наследование. Я же не такой фанат хайлоада, как Артвид.
некоторые админы отключают запись mtime для ускорения работы диска, поэтому стратегия кэша может быть и другой