За последние 24 часа нас посетили 20772 программиста и 1192 робота. Сейчас ищут 634 программиста ...

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

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

  1. cms-lite

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

    С нами с:
    16 янв 2010
    Сообщения:
    53
    Симпатии:
    0
    хотя мне больше нравиться так:

    PHP:
    1. <?
    2.  
    3.  // (c) cms-lite =)
    4.  
    5.  define("__s1__","{");
    6.  
    7.  define("__s2__","}");
    8.  
    9.  class view{    
    10.  
    11.      protected $tpl = "";
    12.      
    13.      protected $from = array();
    14.      
    15.      protected $to = array();          
    16.  
    17.      public function __construct($t){
    18.      
    19.         $this->tpl = file_get_contents($t);
    20.        
    21.      }
    22.        
    23.      public function __set($k,$v){
    24.          
    25.          $this->from[$k] = __s1__.$k.__s2__;
    26.          
    27.          $this->to[$k] = $v;        
    28.          
    29.      }
    30.      
    31.      public function __get($k){
    32.      
    33.          if(isset($this->to[$k]))return $this->to[$k];
    34.          
    35.          return "";
    36.      
    37.      }
    38.        
    39.      public function __toString(){
    40.          
    41.          return str_replace($this->from,$this->to,$this->tpl);
    42.          
    43.      }
    44.      
    45.  }
    46.  
    47. ?>
     
  2. Volt(220)

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

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    А циклы и условия?
     
  3. cms-lite

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

    С нами с:
    16 янв 2010
    Сообщения:
    53
    Симпатии:
    0
    Для рендеринга пассивных шаблонов этого почти достаточно (не хватает некоторых проверок, кэширования и динамических блоков).
    Что же касается активных шаблонов?... А нужно ли логику представления возлагать на шаблоны?
     
  4. Volt(220)

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

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Т.е. для каждой таблицы делать отдельный шаблон?
     
  5. Psih

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

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    PHP:
    1.  
    2. <?php echo get('pager')?>
    3. <table>
    4.     <tr>
    5.         <th>Col1</th>
    6.         <th>Col2</th>
    7.         <th>Col3</th>
    8.         <th>Col4</th>
    9.         <th>Col5</th>
    10.     </tr>
    11.     <?php if (is_set('data')):?>
    12.         <?php foreach (get('data') as $v):?>
    13.             <tr>
    14.                 <td><?php echo $v['col1']?></td>
    15.                 <td><?php echo $v['col2']?></td>
    16.                 <td><?php echo $v['col3']?></td>
    17.                 <td><?php echo $v['col4']?></td>
    18.                 <td><?php echo $v['col5']?></td>
    19.             </tr>
    20.         <?php endforeach;?>
    21.     <?php else:?>
    22.         <tr>
    23.             <td colspan="5" class="hint">No data found</td>
    24.         </tr>
    25.     <?php endif;?>
    26. </table>
    27. <?php echo get('pager')?>
    28.  
    Куда уж там без логики...
     
  6. Mr.M.I.T.

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

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    мм. не лучшее решение
     
  7. [vs]

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

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    я б делал так
    PHP:
    1. <?php
    2. foreach ($pages as $link => $n)
    3. {
    4.         $pnum = new view('./..../pginator_col.tpl');
    5.         $pnum -> link = $link;
    6.         $pnum -> num = $n;
    7.         $view -> pages .= $pnum;
    8. }
    и кэшируем! ;D
     
  8. Psih

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

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Табличные у меня данные, и "Срааать! Срать я хотел на дивы!". Там где контент дивами, там дивы. Где таблицы - там таблицы. Так что, ИМХО, замечание не уместно.
     
  9. Mr.M.I.T.

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

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Psih
    да не про таблицы я. а про вывод ошибок
     
  10. [vs]

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

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    Mr.M.I.T.
    А пустой раздел - не ошибка :)
     
  11. Psih

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

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Вот вот, это же просто информационное сообщение, что данных нет.
     
  12. Mr.M.I.T.

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

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

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

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    У меня в итоге получилось так:
    PHP:
    1.     <?php
    2.     class Template{  
    3.  
    4.         /**
    5.          * Буфер переменных.
    6.          * @var array
    7.          */
    8.         protected $vars=array();
    9.  
    10.         /**
    11.          * Путь к шаблону.
    12.          * @var string;
    13.          */
    14.         protected $path=null;
    15.        
    16.         /**
    17.          * Нужно ли кэшировать шаблон.
    18.          * @var boolean
    19.          */
    20.         protected $needCache=null;
    21.  
    22.         /**
    23.          * Дирректория с кэшем шаблона.
    24.          * @var string
    25.          */
    26.         protected $cacheDir=null;
    27.        
    28.         /**
    29.          * Конструктор
    30.          *
    31.          * @param String $path Путь к файлу шаблона
    32.          */
    33.         public function __construct($path, $cache=null, $dir=null){
    34.             global $vf;
    35.             $this->path=$path;
    36.             $this->needCache= $cache==null ? $vf["tpl"]["needCache"] : $cache;
    37.             $this->cacheDir= $dir==null ? $vf["dir"]["cacheDir"] : $dir;
    38.         }
    39.  
    40.         /**
    41.          * Магическая запись переменной в буфер.
    42.          *
    43.          * @param string $var Имя переменной
    44.          * @param mixed $val Значение переменной
    45.          */
    46.         public function __set($var, $val){
    47.             $this->vars[$var]=$val;
    48.         }
    49.        
    50.         /**
    51.          * Мангическое получение значения переменной.
    52.          *
    53.          * @param string $var Имя переменной
    54.          * @return mixed Значение переменной
    55.          */
    56.         public function __get($var){
    57.             if (isset($this->$var)){
    58.                 return $this->$var;
    59.             }
    60.             return $this->vars[$var];
    61.         }
    62.        
    63.         /**
    64.          * Вытаскивает из массива значения для переменых шаблона.
    65.          *
    66.          * В случае асоциативного массива присваивает переменной шаблона с именем ключа массива соответсвующее значение массива.
    67.          * Если массив нумерованный (или имена начинаются с цифр), то создаются переменные типа vN, где N ключ массива.  
    68.          *
    69.          * @param array $arr Массив со значениями.
    70.          */
    71.         public function arraySet($arr){
    72.             foreach($arr as $key=>$val){
    73.                 if ($key+0==0){
    74.                     $this->$key=$val;
    75.                 }
    76.                 else{
    77.                     $var="v".$key;
    78.                     $this->$var=$val;
    79.                 }
    80.             }
    81.         }
    82.        
    83.         /**
    84.          * Высчитывает хэш шаблона.
    85.          *
    86.          * @return string Хэш шаблона.    
    87.          */
    88.         public function hashCode(){
    89.             $hash = 0;
    90.             $this->ksortVars();
    91.             $hash = md5(serialize($this));
    92.             return $hash;
    93.         }
    94.        
    95.         /**
    96.          * Сортирует массивы переменных шаблона и подшаблонов по ключам.
    97.          */
    98.         public function ksortVars(){
    99.             deepKsort($this->vars);
    100.             foreach($this->vars as $var){
    101.                 if ($var instanceof Template){
    102.                     $var->ksortVars();
    103.                 }
    104.             }
    105.         }
    106.                        
    107.         /**
    108.          * Возвращает имя файла с кэшем.
    109.          *
    110.          * @return string Имя файла с кэшем.    
    111.          */
    112.         protected function getCacheFileName(){
    113.             if(!file_exists($this->cacheDir)){
    114.                 mkdir($this->cacheDir);
    115.             }
    116.             return $this->cacheDir."/".basename($this->path, ".tpl")."_".$this->hashCode();
    117.         }
    118.        
    119.         /**
    120.          * Преобразование шаблона в строку.
    121.          *
    122.          * @return string Результат выполнения шаблона
    123.          */
    124.         public function __toString(){
    125.             if ($this->needCache){
    126.                 $cacheFileName=$this->getCacheFileName();
    127.                 if (file_exists($cacheFileName)){
    128.                     return file_get_contents($cacheFileName);
    129.                 }
    130.                 else{
    131.                     $rez=$this->compile();     
    132.                     file_put_contents($cacheFileName, $rez);
    133.                     return $rez;
    134.                 }
    135.             }
    136.             else{
    137.                 return $this->compile();
    138.             }
    139.         }
    140.        
    141.         /**
    142.          * Выполнение шаблона
    143.          *
    144.          * @return string Результат выполнения шаблона
    145.          */
    146.         public function compile(){
    147.             extract($this->vars);
    148.             ob_start();
    149.             include($this->path);
    150.             return ob_get_clean();
    151.         }
    152.     }
     
  14. Simpliest

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

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

    Volt(220), объясни? Почему у тебя не получилась помойная куча?

    P.S. отдать кеширование и подсчет хешей на откуп самим подшаблонам не?
     
  15. Volt(220)

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

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    1) Стартовали от разных реализаций.
    2) Делал изменения по ходу развития темы.

    1) При первом прогоне подшаблоны закешируются.
    2) Если собирать конечную страницу из кешей подшаблонов, то получатся дополнительные операции чтения с диска, которых можно избежать.
    3) Если подсчет хешей отдать подшаблонам, то надо организовывать цикл по поиску подшаблонов и
    возникает вопрос куда девать эти хеши.
     
  16. Simpliest

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

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    никуда, ты берешь хеш хешей.
    Т.е. вместо вытаскивания переменных, ты просто спрашиваешь у подшаблона его хеш.

    Зачем?
    Есть два варианта:
    - тупо спрашивать "дай контент" и класть его в свой кеш не беспокоясь о том, что есть кеши подшаблонов.
    - говорить дай хеш, а потом уже решать нужен ли нам контент.

    Я бы выбрал первый вариант. То что подшаблон чего-то там кеширует - меня не должно волновать.
    В крайнем случае можешь принудительно подшаблонам выставлять no_cache
     
  17. Volt(220)

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

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Я так сначала и делал.

    Что тогда делать с остальными переменными, в том числе с массивами?

    Примерно так и происходит.
    Шаблон смотрит: "А не закеширован ли я? Закеширован? Тогда на тебе кеш. Не закеширован? Тогда сейчас выполнюсь."
    И во время выполнения уже запрашивается контент подшаблона, который решает то ли свой кеш отдать, то ли выпониться.
     
  18. Mr.M.I.T.

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

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    мм. а зачем вам вообще этот кеш нужен? на практике применения почти не находит
     
  19. Mr.M.I.T.

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

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    я походу не в теме.
    но..
    PHP:
    1. public function __construct($path, $cache=null, $dir=null){
    2.              global $vf;
     
  20. Volt(220)

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

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Мне он нужен для законченности идеи. Чтобы когда понадобиться
    1) Мозг уже имел некоторую информацию по теме.
    2) можно было взять готовое.

    Что именно смущает? global $vf;? Это массив настроек. Я пока не нашел более удобного способа для хранения настроек.
     
  21. [vs]

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

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    Код (Text):
    1. Fatal error: Call to undefined function deepKsort()
    o_0
     
  22. Mr.M.I.T.

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

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    PHP:
    1. global $vf;
    это передача массива настроек в конструктор. есть много более удобных способов хранения и передачи настроек чем массив в глобальной области.
    не очень хороший подход.
    идея типа хочу кеширование не идея.
    попробую дать тебе идею. хочу кеширование чтоб выйграть на компиляции статики в шаблонах.
    хотя, для натив пхп, это тоже бредовая идея =)
     
  23. Volt(220)

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

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    [vs]
    Логично. =))
    PHP:
    1. <?php  
    2. function deepKsort(&$arr){
    3.         ksort($arr);
    4.         foreach($arr as $key=>$val){
    5.             if (is_array($val)){
    6.                 deepKsort($arr[$key]);
    7.             }
    8.         }
    9.     }
    10.  
     
  24. Volt(220)

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

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Константы, ini файлы, подключение файла настроек в самом в конструкторе. Пока больше ничего не вспоминается.
    Если есть желание обсудить этот вопрос, то я создам отдельную тему.

    не-не... Идея типа хочу знать как можно сделать кеширование.
     
  25. Mr.M.I.T.

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

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    1) вопрос не в хранении а в использовании. регистр.
    2) есть ещё 100 реализаций этого =)