За последние 24 часа нас посетили 18542 программиста и 1623 робота. Сейчас ищет 1761 программист ...

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

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

  1. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    А что с остальными переменными?
     
  2. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    PHP:
    1. <?php
    2. $view = new Template('./1.tpl',1,'.');
    3. $view -> var = new Template('./2.tpl',1,'.');
    в кэше 1.tpl и так оказывается содержимое 2.tpl. В связи с этим вопрос - зачем вообще когда-либо кэшировать подшаблоны?
     
  3. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Так я не понял, вопрос в хранении или нет? =))

    В смысле то, что константные значения принято делать в верхнем регистре?

    Где посмотреть?


    1)Либо надо от каждой считать хэш и идти в глубь массивов,
    2)Либо не идти в глубь массивов, а превращать их в строку (serialize, jspn_encode и т.д.) и тогда возникает вопрос зачем так сложно, когда можно сразу сериализовать весь объект.
    3)Либо надо удалять/заменять подшаблоны.
    Я прошел по второму пути.
    А какой выигрыш нам даст глубинный расчет хэша подшаблонов?


    1) Не хочешь не кешируй:
    PHP:
    1. <?php
    2.  $view = new Template('./1.tpl',1,'.');
    3.  $view -> var = new Template('./2.tpl',false);
    4.  
    или
    PHP:
    1. <?php
    2.  $vf["tpl"]["needCache"]=false;
    3.  $view = new Template('./1.tpl',true,'.');
    4.  $view -> var = new Template('./2.tpl');
    5.  
    2) Есть шаблон с двумя подшаблонами. При изменении одного подшаблона пересчитывается один подшаблон и главный шаблон, а второй подшаблон берется из кеша.
    3) Есть шаблон который используется в нескольких других шаблонах которые не кешируются.
     
  4. Mr.M.I.T.

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

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    нда.
    в передаче настроек вопрос был.
    не регистр а реестр. всяко бывает. опечатался
     
  5. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Mr.M.I.T.
    Отдельный класс/объект реестра вместо массива?
    Инкапсуляция данных против небольшого увеличения сложности.
    Возможно это имеет смысл.
    Спасибо за совет.
     
  6. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Если использовать сериализованые массивы, то при unserialize будут заново создаваться экземпляры классов, быстрее собрать массивы обычных переменных и их использовать :))))
     
  7. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    [vs]
    А у меня нет unserialize. :p
     
  8. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Причем тут глубинный расчет хэша?
    Выигрыш будет в том, что у нас не будет левых методов и каждый объект сам контролирует свое состояние.

    Дело в том, что лично меня бы не волновало, что
    PHP:
    1. <?php
    2. $class1 = new stdClass
    3. $class1->a = 'a';
    4. $class1->b = 'b';
    5.  
    6. $class2 = new stdClass
    7. $class2->b = 'b';
    8. $class2->a = 'a';
    9.  
    10. md5(serialize($class1)) != md5(serialize($class2));
    Вам захотелось контролировать эти ситуации - ради бога. Только не надо забирать данные у подшаблонов и хешировать их.
    Мы говорим ему - сделай. А не - дай нам данные, мы сделаем.
    Скажи ему - "дай свой хеш". И все.

    В твоем случае хеш подшаблонов вообще не используется - ты заставляешь их себя упорядочивать - это вполне вариант.
     
  9. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Volt(220)
    Круто, еще в 4 раза быстрее :cool:
     
  10. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Simpliest
    Ты имеешь в виду нечто вроде такого:
    PHP:
    1. <?php
    2. public function hashCode(){
    3.              $hash = 0;
    4.              $vars=$this->vars;
    5.              foreach($vars as $key=>$var){
    6.                  if ($var instanceof Template){
    7.                      $vars[$key] = $var->hashCode();
    8.                  }
    9.              }
    10.              $hash=md5(serialize($vars));
    11.              return $hash;
    12.          }
    13.  
    ?

    [vs]
    Ага.
    Только придется решать вопросы:
    как контролировать разрастание количества файлов кеша (чистить руками или создавать некий класс "манагер кеша") и
    как ловить изменение шаблона (программно или ручками удалять хеш)
     
  11. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Ух... как мне это не нравится :) ну как вариант.

    меня больше устраивает просто
    Код (Text):
    1. md5(serialize($this));
    По времени последнего доступа.
     
  12. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Можно именовать файл кэша так
    PHP:
    1. md5($path).md5(ыукшфдшяу($this))
    потом делать glob по первой части имени, если есть - сравнивать вторую часть с хэшем текущего объекта, если совпадает - грузить, если нет - удалять файл и компилить...
     
  13. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    И эти люди беспокоятся о скорости.... Бгг....
     
  14. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Simpliest
    Мы достаточно долго обсуждали, что подшаблоны должны выдавать свой хеш вместо переменных вот я и пытался понять как это согласуется с моим классом и куда это всунуть.

    Я, наверное, далеко не сразу бы увидел такую мысль... но
    вопрос больше в том кто и как будет убирать лишние файлы, чем какие именно файлы удалять.

    [vs]
    1) Идея как раз в том, что можно хранить несколько часто используемых кешей одного шаблона.
    2) Нафига md5($path), когда у меня используется basename($this->path, ".tpl") и делай glob по нему, если очень надо. Опять же админ при взгляде на файлы кеша быстро поймет какой файл от какого шаблона.
    3) По-моему это не совсем дело шаблона... Точнее я пока не вижу хорошего способа прикрепить задачу очистки от старых кешей к классу Template.
     
  15. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    cron

    Или ты полагаешь что
    в каждом шаблоне - это верх разума? :)
     
  16. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    если только вписать в имя файла хэши подшаблонов, потом разбивать это имя на подстроки по 32 символа и проверять хэши :)))
    тогда возникнет ошибка, если грубо говоря один шаблон называется b, а второй - ba.
     
  17. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Simpliest
    идею вроде понял. Буду думать.

    [vs]
    Ошибка возникнет, если есть два шаблона b.tpl, у которых одинаковый набор переменных, но разная внутренность и то у них будет разный хеш, т.к. в serialize($this) включается свойство $path.
     
  18. cms-lite

    cms-lite Активный пользователь

    С нами с:
    16 янв 2010
    Сообщения:
    53
    Симпатии:
    0
    я вот подумал, было бы проще, если бы разработчики PHP (дабы избавить многих от изобретения велосипеда) сделали режим трансляции файлов с расширением *.tpl, при котором транслятор "понимал" бы только ограниченный набор функций, но достаточный для программной вёрстки веб-страниц...
     
  19. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    было бы проще, если бы разработчики PHP разрабатывали что-нибудь другое.
     
  20. cms-lite

    cms-lite Активный пользователь

    С нами с:
    16 янв 2010
    Сообщения:
    53
    Симпатии:
    0
    Решил развить идею пассивного шаблонизатора.
    Это конечно не FastTemplate, но основная цель -
    разделение PHP и HTML достигнута.

    const.php:

    PHP:
    1. <?php
    2.  
    3.   // cms-lite (c) =)
    4.  
    5.   define( "__START__", microtime(true));
    6.   define( "__QUERY__", intval($_SERVER["QUERY_STRING"]) );
    7.   define( "__tpl_path__" , "./%s.tpl" );
    8.   define( "__chr_open__" , "{");
    9.   define( "__chr_close__", "}");
    10.   define( "__begin_open__" , "{begin ");
    11.   define( "__begin_close__", "}");
    12.   define( "__end_open__" , "{end ");
    13.   define( "__end_close__", "}");
    14.   define( "__str_site__" , "Мой сайт" );
    15.   define( "__str_submit__" , "Далее");
    16.   define( "__err_tpl_not_found__", "<b>Ошибка: </b>шаблон %s не найден" );
    17.   define( "__err_block_not_found__", "<b>Ошибка: </b>блок %s не найден" );
    18.  
    19. ?>
    globals.php:

    PHP:
    1. <?php
    2.  
    3.   $arrNodes = array(
    4.     0=>"Главная",
    5.     1=>"Пользователи",
    6.     2=>"Регистрация",
    7.     3=>"Вход",
    8.     4=>"Выход",
    9.     5=>"Контакты",
    10.     6=>"Добавить контакт",      
    11.     7=>"Удалить контакт",        
    12.     8=>"Форумы",          
    13.   );
    14.  
    15.   $arrChilds = array(
    16.     "root"=>array(0),
    17.     0=>array(1,8),
    18.     1=>array(2,3,4,5),
    19.     5=>array(6,7),    
    20.   );
    21.  
    22. ?>
    23.  
    class.Template.php:

    PHP:
    1. <?php
    2.  
    3.   class Template{
    4.  
    5.     private $_strTpl;
    6.  
    7.     private $_arrBlocks = array();
    8.  
    9.     public function __construct($strName)
    10.     {
    11.       $p = sprintf(__tpl_path__,$strName);
    12.  
    13.       if( file_exists($p) ){
    14.         $this->_strTpl = file_get_contents($p);
    15.       }else{
    16.         exit(sprintf(__err_tpl_not_found__,$strName));
    17.       }
    18.      
    19.       $this->_strTpl = $this->detectBlock($this->_strTpl);
    20.     }
    21.    
    22.     private function detectBlock($strTpl){
    23.       $e1 = explode(__begin_open__, $strTpl, 2);
    24.      
    25.       if( sizeof($e1)<2 ){
    26.         return $strTpl;
    27.       }  
    28.      
    29.       $e2 = explode(__begin_close__, $e1[1], 2);
    30.      
    31.       if( sizeof($e2)<2 ){
    32.         return $strTpl;
    33.       }
    34.      
    35.       $b = $e2[0];
    36.       $e3 = explode(__end_open__ . $b . __end_close__, $e2[1], 2);
    37.      
    38.       if( sizeof($e3)<2 ){
    39.         return $strTpl;
    40.       }
    41.        
    42.       $this->_arrBlocks[$b] = $this->detectBlock($e3[0]);
    43.       $s = $this->detectBlock($e3[1]);
    44.      
    45.       return $e1[0] . __chr_open__ . $b . __chr_close__ . $s;                
    46.     }
    47.  
    48.     public function __get($strName)
    49.     {
    50.      
    51.       if( !isset($this->_arrBlocks[$strName]) ){
    52.         exit(sprintf(__err_block_not_found__,$strName));
    53.       }
    54.  
    55.       return $this->_arrBlocks[$strName];
    56.     }
    57.  
    58.     public function __toString()
    59.     {
    60.       return $this->_strTpl;
    61.     }
    62.  
    63.   }
    64.  
    65. ?>
    66.  
    class.View.php:
    PHP:
    1.  
    2. <?php
    3.  
    4.   class View{
    5.  
    6.     private $_strTpl="";
    7.  
    8.     private $_arrFrom=array();
    9.  
    10.     private $_arrTo=array();
    11.  
    12.     public function __construct($strTpl)
    13.     {
    14.       $this->_strTpl = $strTpl;
    15.     }
    16.  
    17.     public function __set($strVar, $strVal)
    18.     {
    19.       $this->_arrFrom[$strVar] = __chr_open__ . $strVar . __chr_close__;
    20.       $this->_arrTo[$strVar] = $strVal;
    21.     }
    22.  
    23.     public function __get($strVar)
    24.     {
    25.      
    26.       if( !isset($this->_arrTo[$strVar]) ){
    27.         $this->__set($strVar, "");
    28.       }
    29.  
    30.       return $this->_arrTo[$strVar];
    31.     }
    32.    
    33.     public function __toString()
    34.     {
    35.       return str_replace($this->_arrFrom,$this->_arrTo,$this->_strTpl);
    36.     }
    37.    
    38.   }
    39.  
    40. ?>
    И небольшой примерчик вдогонку, в котором
    генерируется иерархическое меню и простенькая
    форма.

    index.php:

    PHP:
    1. <?php
    2.  
    3.   error_reporting($_SERVER["SERVER_ADDR"]==="127.0.0.1" ? E_ALL : 0);
    4.  
    5.   include("./const.php");
    6.   include("./globals.php");
    7.   include("./class.Template.php");
    8.   include("./class.View.php");
    9.  
    10.   if($_POST){
    11.     $intSelect = isset($_POST["select"]) ? intval($_POST["select"]) : 0;
    12.     header("Location:/?".$intSelect);
    13.     exit();
    14.   }
    15.  
    16.   $tpl_main = new Template("main");
    17.   $tpl_menu = new Template("menu");
    18.   $tpl_form = new Template("form");
    19.  
    20.   function build_menu($i)
    21.   {
    22.     global $tpl_menu,$arrNodes,$arrChilds;
    23.  
    24.     $menu = new View($tpl_menu);
    25.    
    26.     foreach( $arrChilds[$i] as $q ){
    27.  
    28.       if( isset($arrChilds[$q]) ){
    29.         $b = ( $q === __QUERY__ ) ? "item3" : "item4";
    30.       }else{
    31.         $b = ( $q === __QUERY__ ) ? "item1" : "item2";
    32.       }
    33.  
    34.       $item = new View($tpl_menu->$b);
    35.  
    36.       if( $q!==__QUERY__ ){
    37.         $item->href = "/?".$q;
    38.       }
    39.  
    40.       $item->title = $arrNodes[$q];
    41.  
    42.       if( isset($arrChilds[$q]) ){
    43.         $item->menu = build_menu($q);
    44.       }
    45.  
    46.       $menu->items .= $item;
    47.     }
    48.  
    49.     return $menu;
    50.   }
    51.  
    52.   $form = new View($tpl_form);
    53.   $form->href = "/";
    54.  
    55.   foreach( $arrNodes as $q=>$t ){
    56.     $b = ( $q===__QUERY__ ) ? "option1" : "option2";
    57.     $option = new View($tpl_form->$b);
    58.     $option->value = $q;
    59.     $option->title = $t;    
    60.     $form->options .= $option;
    61.   }
    62.  
    63.   $form->str_submit = __str_submit__;
    64.  
    65.   $main = new View($tpl_main);
    66.   $main->site  = __str_site__;
    67.   $main->title = $arrNodes[__QUERY__];
    68.   $main->menu  = build_menu("root");
    69.   $main->form  = $form;
    70.  
    71.   echo $main;
    72.   echo microtime(true) - __START__;
    73.  
    74. ?>
    main.tpl:

    Код (Text):
    1. <html>
    2.   <head>
    3.     <title>{site} - {title}</title>
    4.   </head>
    5.   <body>
    6.     {menu}
    7.     <hr>
    8.     {form}
    9.   </body>
    10. </html>
    menu.tpl:

    Код (Text):
    1. <ul>
    2.   {begin items}
    3.     {begin item1}<li>{title}{end item1}
    4.     {begin item2}<li><a href="{href}">{title}</a>{end item2}
    5.     {begin item3}<li>{title}{menu}{end item3}
    6.     {begin item4}<li><a href="{href}">{title}</a>{menu}{end item4} 
    7.   {end items}
    8. </ul>
    form.tpl:

    Код (Text):
    1. <form action="{href}" method="post">
    2.   <select name="select">
    3.     {begin options}  
    4.       {begin option1}<option value="{value}" selected>{title}{end option1}
    5.       {begin option2}<option value="{value}">{title}{end option2}      
    6.     {end options}      
    7.   </select>
    8.   <br>  
    9.   <input type="submit" value="{str_submit}">
    10. </form>
     
  21. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Twig детектед
     
  22. Костян

    Костян Активный пользователь

    С нами с:
    12 ноя 2009
    Сообщения:
    1.724
    Симпатии:
    1
    Адрес:
    адуктО
    HTML:
    1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    2. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    3. <link rel="stylesheet" href="default.css" type="text/css">
    4. <script type="text/javascript" src="jquery.min.js"></script>
    5. <script type="text/javascript" src="KCZ.js"></script>
    6. </head>
    7. <body onload="Update('content', document.getElementById('content'));">
    8.     <table width="100%" height="100%" cellpadding="0" cellspacing="0" border="0">
    9.     <tr height="80px" onclick="Update('content', document.getElementById('content'), '<?php echo KCZ_Escape::Url($Data->MainPageUrl)?>');" class="header">
    10.         <td align="center">
    11.             <div id="header">
    12.             </div>
    13.         </td>
    14.     </tr>
    15.     <tr>
    16.         <td>
    17.             <div id="menu">
    18.                 <?php echo $Data->MainMenu?>
    19.             </div>
    20.         </td>
    21.     </tr>
    22.     <tr valign="top" height="100%">
    23.         <td>
    24.             <div id="content">
    25.             <?php echo KCZ_Escape::Html($Data->OffJavaScript)?></div>
    26.             </div>
    27.         </td>
    28.     </tr>
    29.     <tr>
    30.         <td>
    31.             <div id="footer">&nbsp;</div>
    32.             <div id="debug">&nbsp;</div>
    33.         </td>
    34.     </tr>
    35. </body>
    36. </html>
    ))
     
  23. cms-lite

    cms-lite Активный пользователь

    С нами с:
    16 янв 2010
    Сообщения:
    53
    Симпатии:
    0
  24. Костян

    Костян Активный пользователь

    С нами с:
    12 ноя 2009
    Сообщения:
    1.724
    Симпатии:
    1
    Адрес:
    адуктО
    cms-lite
    что за бред?