За последние 24 часа нас посетили 17928 программистов и 1613 роботов. Сейчас ищут 1444 программиста ...

Native Шаблонизатор

Тема в разделе "Решения, алгоритмы", создана пользователем kostyl, 18 ноя 2008.

  1. kostyl

    kostyl Guest

    Раз уж все выкладывают, то и я выложу шаблонизатор:
    PHP:
    1.  
    2. <?php
    3. /**
    4. *
    5. * @package Template
    6. * @version $Id: template.php,v 0.2 Exp $
    7. * @copyright (c) kostyl
    8. * @license freeware
    9. *
    10. */
    11. class TemplateException extends Exception {}
    12. /**
    13. *AbstractTemplate
    14. *абстрактный слой шаблонизатора
    15. */
    16. abstract class AbstractTemplate {
    17.     /**
    18.     *Добавляет переменную парсинга
    19.     *@param $name имя переменной в шаблоне
    20.   *@param $value значение переменной в скрипте
    21.     */
    22.   abstract function AddVar($name, $value);
    23.   /**
    24.   *Возвращает контент страницы
    25.   *@param $file файл шаблона
    26.   */
    27.     abstract function Prepare($file = NULL);
    28.     /**
    29.     *Выводит в браузер контент страницы
    30.     */
    31.     abstract function Display();
    32.   /**
    33.   *Устанавливает режим кэширования
    34.   *@param $Cache объект AbstractTemplateCache для кэширования либо NULL по умолчанию
    35.   */
    36.   abstract function SetCacheMode(AbstractTemplateCache $Cache = NULL);
    37.   /**
    38.   *Возвращает TRUE если кэширование используется
    39.   */
    40.   abstract function GetCacheMode();
    41.   /**
    42.   *Возвращает TRUE елси включено кэширование и кэш-файл актуальный
    43.   */
    44.   abstract function IsCached();
    45.  
    46. }
    47. /**
    48. *AbstractTemplateCache
    49. *абстрактный словй кэша шаблонизатора
    50. */
    51. abstract class AbstractTemplateCache {
    52.   /**
    53.   *Проверяет есть ли кэш-файл готовый к использованию
    54.   */
    55.     abstract function IsActual();
    56.   /**
    57.   *Читает кэш-файл и возвращает его контент
    58.   */
    59.     abstract function Read();
    60.   /**
    61.   *Сохраняте кэш-файл
    62.   *@param $content кэш-контент
    63.   */
    64.     abstract function Write($content);
    65. }
    66. /**
    67. *TemplateCache extends AbstractTemplateCache
    68. *кэширует шаблон по mtime !!!
    69. */
    70. class TemplateCache extends AbstractTemplateCache {
    71.   protected $_id;
    72.   protected $_expired;
    73.   /**
    74.   *Конструктор
    75.   *@param $cache_id кэш-файл
    76.   *@param $expired время молодости кэш-файла
    77.   */
    78.   function __construct($cache_id, $expired)
    79.   {
    80.     $this->_id      = $cache_id;
    81.     $this->_expired = $expired;
    82.   }
    83.   /**
    84.   *Проверяет актуален ли кэш-файл
    85.   */
    86.   function IsActual()
    87.   {
    88.     if (!($this->_id)) {
    89.         return FALSE;
    90.     }
    91.     if (!file_exists($this->_id)) {
    92.         return FALSE;
    93.     }
    94.     if (!($create_time = filemtime($this->_id))) {
    95.         return FALSE;
    96.     }
    97.     if (($create_time + $this->_expired) < time()) {
    98.       @unlink($this->_id);
    99.       return FALSE;
    100.     }
    101.     return TRUE;
    102.   }
    103.   /**
    104.   *Читает с диска и возвращает кэш-файл
    105.   */
    106.   function Read()
    107.   {
    108.     if($this->IsActual()) {
    109.         return @file_get_contents($this->_id);
    110.     }
    111.     return FALSE;
    112.   }
    113.   /**
    114.   *Пишет на диск кэш-файл
    115.   */
    116.   function Write($content)
    117.   {
    118.     if($this->_id) {
    119.       return @file_put_contents($this->_id, $content);
    120.     }
    121.   }
    122.   /**
    123.   *Удаляет кэш файл
    124.   */
    125.   function Delete()
    126.   {
    127.     if (file_exists($this->_id)) {
    128.       @unlink($this->_id);
    129.     }
    130.   }
    131.   /**
    132.   *Удаляет группу кэш файлов в директории $cache_dir имена которых содержат $filename_mach
    133.   *@param $cache_dir
    134.   *@param $filename_mach
    135.   */
    136.   static function DeleteCache($cache_dir, $filename_mach)
    137.   {
    138.     if ($handle = @opendir($cache_dir)) {
    139.       while (($file = readdir($handle)) !== FALSE ) {
    140.         if(preg_match('/'. $filename_mach . '/', $file)) {
    141.           unlink($cache_dir . $file);
    142.         }
    143.       }
    144.       closedir($handle);
    145.     }
    146.   }
    147. }
    148. /*
    149. *NaitiveParsingTemplate extends AbstractTemplate
    150. *инклудит шаблон для найтивного парсинга
    151. *использует буферизацию вывода естественно
    152. */
    153. class NaitiveParsingTemplate extends AbstractTemplate {
    154.   protected   $_vars = array();
    155.   protected   $_file;
    156.   protected   $_Cache = NULL;
    157.   /**
    158.   *Конструктор
    159.   *@param $file файл шаблона
    160.   */
    161.   function __construct($file = NULL)
    162.   {
    163.     $this->_file = $file;
    164.   }
    165.   /**
    166.     *Добавляет переменную парсинга
    167.     *@param $name имя переменной в шаблоне
    168.   *@param $value значение переменной в скрипте
    169.     */
    170.   function AddVar($name, $value)
    171.   {
    172.     $this->_vars[$name] = ($value instanceof AbstractTemplate) ? $value->Prepare() : $value;
    173.   }
    174.   /**
    175.   *Парсит шаблон возвращая контент
    176.   *@param $file файл шаблона
    177.   */
    178.   protected function Parse($file = NULL)
    179.   {
    180.     if ($file) {
    181.         $this->_file = $file;
    182.     }
    183.     if (!$this->_file) {
    184.         throw new TemplateException(__CLASS__ . '::Parse()=>Template file is not set');
    185.     }
    186.     $varcount = extract($this->_vars);
    187.     if ($varcount !== count($this->_vars)) {
    188.         throw new TemplateException(__CLASS__ . '::Parse()=>Extract vars error ' . $varcount . '<>' . count($this->_vars));
    189.     }
    190.     ob_start();
    191.     if(!file_exists($this->_file)) {
    192.         throw new TemplateException(__CLASS__ . '::Parse()=>Tamplate is not found');
    193.     }
    194.     include($this->_file);
    195.     return ob_get_clean();
    196.   }
    197.   /**
    198.   *Возвращает контент страницы
    199.   *@param $file файл шаблона
    200.   */
    201.   function Prepare($file = NULL)
    202.   {
    203.     if ($this->GetCacheMode()) {
    204.       if ($this->_Cache->IsActual()) {
    205.         return  $this->_Cache->Read();
    206.       }
    207.       else {
    208.         $content = $this->Parse($file);
    209.         $this->_Cache->Write($content);
    210.         return $content;
    211.       }
    212.     }
    213.     else {
    214.       return $this->Parse($file);
    215.     }
    216.   }
    217.     /**
    218.     *Выводит в браузер контент страницы
    219.     */
    220.   function Display()
    221.   {
    222.     header('Expires: 0');
    223.     header('Pragma: no-cache');
    224.     header('Cache-Control: no-cache, no-store, max-age=0, s-maxage=0, must-revalidate');
    225.     echo $this->Prepare();
    226.   }
    227.   /**
    228.   *Устанавливает режим кэширования
    229.   *@param $Cache объект AbstractTemplateCache для кэширования либо NULL по умолчанию
    230.   */
    231.   function SetCacheMode(AbstractTemplateCache $Cache = NULL)
    232.   {
    233.     $this->_Cache = $Cache;
    234.   }
    235.   /**
    236.   *Возвращает TRUE если кэширование используется
    237.   */
    238.   function GetCacheMode()
    239.   {
    240.     if(is_object($this->_Cache)) {
    241.       return TRUE;
    242.     }
    243.     return FALSE;
    244.   }
    245.   /**
    246.   *Возвращает TRUE елси включено кэширование и кэш-файл актуальный
    247.   */
    248.   function IsCached()
    249.   {
    250.     if ($this->GetCacheMode())  {
    251.       return $this->_Cache->IsActual();
    252.     }
    253.     return FALSE;
    254.   }
    255. }
    256. /**
    257. *Абстрагируемся
    258. */
    259. final class Template extends NaitiveParsingTemplate {}
    260.  
    Пример для профиля пользователя, допустим:
    PHP:
    1.  
    2. <?php
    3. $TplUserPorfile = new Template('profile.html');
    4. $TplUserPorfile->SetCacheMode(new TemplateCache('./cache/profile' .
    5.                                                 md5($_GET['userid']) .
    6.                                                 '.ch', 60*60*24*31));
    7. if(!$TplUserPorfile->IsCached()) {
    8.   $TplUserPorfile->AddVar('L_NAME', getUserName($_GET['userid']));
    9.   $TplUserPorfile->AddVar('L_EMAIL', getUserEmail($_GET['userid']));
    10. }
    11. $TplUserPorfile->Display();
    12.  
    Ну и в profile.html должно быть написано:
    PHP:
    1.  
    2. <?php echo $L_NAME?>
    3. <?php echo $L_EMAIL?>
    4.  
    Если надо удалить кэшь:
    PHP:
    1.  
    2. <?php
    3. TemplateCache::DeleteCache('./cache/profile' . md5($_GET['userid']) );
    4.  
    Вот такие блины с котятами.
     
  2. kostyl

    kostyl Guest

    Пожелания будут?
     
  3. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    зачем столько классов? 0о
    у меня лично шаблонизатор с такими же возможностями занимает 80 строк кода ;)
     
  4. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    вот такое не одобряю
    а если у меня за раз в 2 местах используется этот шаблон но с разными зачениями?
    что 2 раза делать include или file_get_contents
    кеширование кстати при натив пхп используется редко имхо...

    так же несколько раз создавать один и тот же объект, ну имхо - не комильфо
    такой запись выглядит немного...мм, странно ;)
     
  5. kostyl

    kostyl Guest

    это не обязательно согласен
    ну один метод добавить и всё...
     
  6. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    в AddVar стоит добавить поддержку массивов
     
  7. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    не стоит забывать про magic_quotes ;)
     
  8. kostyl

    kostyl Guest

    оу ес!..
     
  9. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Я хуею дорогая редакция!
     
  10. kostyl

    kostyl Guest

    да все мы тут хуеем...
     
  11. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Это подход, который называют OOP ради OOP.

    Реально нужен один класс шаблонизатора и всё. Остальное - излишки.
     
  12. kostyl

    kostyl Guest

    Ну ладно, можете инкапсульнуть кэш в шаблон, удалить абстрактный слой и уту хрень в конце... :)
     
  13. черт, у меня два? )

    DatabaseDriver и Database =0
     
  14. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Олег,
    это потому что у тебя кросс БД?
     
  15. Хм. Ну вообще она кросс, да. Но просто я не люблю сваливать много кода в один класс, и предпочитаю правильное наследование. Я же не такой фанат хайлоада, как Артвид.
     
  16. kostyl

    kostyl Guest

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