Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Шаблонизатор 
:(
    Опции темы
CyClon
Дата 23.2.2008, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 838
Регистрация: 3.12.2005

Репутация: 3
Всего: 4



Цитата
CyClon, "без компиляции нерационально" - это заблуждение.
Миллионы РНР скриптов рабтают без компиляции и кеширования. И прекрасно работают.
Как я уже не раз говорил, работа с шаблоном - далеко не "бутылочное горлышко" веб-приложения. Конечно, самопальные шаблонизаторы на регулярках отстают по скорости от модулей на С и шаблонов на РНР, но не настолько, чтобы в первую голову заботиться об их производительности.
Так что, вполне можно пользоваться и этим "каркасом" =)


Нерациональность в данном случае - это то, что шаблонизатор будет пожирать больше всех ресурсов, чем остальные модули сайта. Там используются регурарыные выражения, которые сами по себе прожорливы, к тому же их много. Особенно в сложных шаблонах. Да и тот же кэш или компилятор написать труда не составит smile Для меня сложнее все продумать так, чтобы потом не было гемора при дальнейшей разработки, в связи с этим и задался поиском книги по ООА smile


--------------------
user posted image
PM   Вверх
GeneralElectric
Дата 23.2.2008, 17:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 797
Регистрация: 11.1.2008

Репутация: 13
Всего: 16



ну-ну. в шаблоне у нас уже откуда-то взялись регулярные выражения. и он пожрал все ресурсы. 
просто фильм ужасов.

интересно, что среди всех любителей порассуждать о производительности почему-то не встречается людей, действительно разрабатывавших серьёзно нагруженные приложения.

Это сообщение отредактировал(а) GeneralElectric - 23.2.2008, 17:36
PM MAIL   Вверх
CyClon
Дата 24.2.2008, 00:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 838
Регистрация: 3.12.2005

Репутация: 3
Всего: 4



Имелось ввиду что в шаблонизаторе используются регулярные выражения и в сложных шаблонах слишком часто происходит их вызов (много блоков / переменных и т.п.). Так ясно?


--------------------
user posted image
PM   Вверх
CyClon
Дата 24.2.2008, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 838
Регистрация: 3.12.2005

Репутация: 3
Всего: 4



Немного переписал, сделал, чтоли, "более абстрактным" xD Тем, кто искал простейший шаблонизатор, ловите...

Шаблон (templates/lite/main.html)
Код
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
  <head>
    <title>{TITLE}</title>
  </head>
  <body>
    <h1>{WELCOME}</h1>
    <ul>
      <!-- BEGIN blocks-left -->
      <li>{BLOCK:NAME} - {BLOCK:VALUE}</li>
      <!-- END blocks-left -->
    </ul>
    <br />
    <br />
    {MAIN}
    <br />
    <br />
    <!-- BEGIN blocks-foot -->< <b>{BLOCK:VALUE}</b> ><!-- END blocks-foot -->
  </body>
</html>


Шаблонизатор (kernel/classes/Template.class.php)
Код
<?php

class Template
{
    private $template;
    private $variables;
    private $blocks;

    public function __construct($template)
    {
        if (file_exists($template)) {
            $this->template = file_get_contents($template);
        } else {
            $this->template = '';
            trigger_error('Not found: ' . $template);
        }
    }

    public function assign($data, $blocks = null)
    {
        if ($blocks == null) {
            foreach ($data as $name => $value) {
                $this->variables[$name] = $value;
            }
        } else {
            foreach ($data as $name => $value) {
                $this->blocks[$blocks][$name] = $value;
            }
        }
    }

    public function display()
    {
        $this->parse();
        print $this->template;
    }

    private function parse()
    {
        $this->template = preg_replace('~<!-- BEGIN (.+) -->(.+)<!-- END (.+) -->~esU', '$this->parseBlocks(\'\\1\', \'\\2\', \'\\0\')', $this->template);
        foreach ($this->variables as $key => $value) {
            $this->template = str_replace('{' . $key . '}', $value, $this->template);
        }
    }

    private function parseBlocks($blocks, $template, $pattern)
    {
        if (isset($this->blocks[$blocks])) {
            $result = '';
            foreach ($this->blocks[$blocks] as $name => $value) {
                $result .= str_replace(array('{BLOCK:NAME}', '{BLOCK:VALUE}'), array($name, $value), rtrim($template));
            }
            return ltrim($result);
        } else {
            return $pattern;
        }
    }
}


Использование (index.php)
Код
<?php

error_reporting(E_ALL);
ini_set('display_errors', '1');

require_once 'kernel/kernel.php';

if (isset($_GET['do']) && file_exists('modules/' . $_GET['do'] . '/main.php')) {
    include 'modules/' . $_GET['do'] . '/main.php';
} else {
    include 'modules/' . CONFIG_DEFAULT_MODULE . '/main.php';
}

$variables = array('TITLE' => 'SH-Framework',
                   'WELCOME' => 'Welcome to party! :)',
                   'MAIN' => main(),
                   );

$blocks_left = array('Block 1' => 'Content 1',
                     'Block 2' => 'Content 2',
                     'Block 3' => 'Content 3',
                     );

$blocks_foot = array('Content 1', 'Content 2', 'Content 3');

$tpl = new Template('templates/lite/main.html');
$tpl->assign($variables);
$tpl->assign($blocks_left, 'blocks-left');
$tpl->assign($blocks_foot, 'blocks-foot');
$tpl->display();


Результат
Код
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
  <head>
    <title>SH-Framework</title>
  </head>
  <body>
    <h1>Welcome to party! :)</h1>
    <ul>
      <li>Block 1 - Content 1</li>
      <li>Block 2 - Content 2</li>
      <li>Block 3 - Content 3</li>
    </ul>
    <br />
    <br />
    This is /var/www/localhost/htdocs/cms/modules/news/main.php
    <br />
    <br />
    < <b>Content 1</b> >< <b>Content 2</b> >< <b>Content 3</b> >
  </body>
</html>



--------------------
user posted image
PM   Вверх
awers
Дата 24.2.2008, 21:21 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1465
Регистрация: 22.3.2006
Где: Россия, Таганрог

Репутация: 21
Всего: 31



ну чем же вам XML/XSL не угодили то? ведь все проще чем вы тут расписываете. могу дать код шаблонного движка который делал сравнительно недавно. Тут и блоки данных и динамическая подгрузка частей шаблонов. Тестовая версия..

modules/mod_templates.php

Код

<?php

/**
 * Модуль для работы с XSLT шаблонами
 *
 * @author awers
 * @package awFrameWork
 */

/**
 * Основной класс
 *
 */
class mod_templates{
    /**
     * Экземпляр класса DOMDocument
     *
     * @var DOMDocument
     */
    private $dom;
    /**
     * Корневой элемент (root)
     *
     * @var DOMElement
     */
    private $document;
    /**
     * Массив коллекций
     *
     * @var array
     */
    private $collections;
    /**
     * XSLT процессор
     *
     * @var XSLTProcessor
     */
    private $xslt;
    /**
     * Зарезервированные коллекции
     *
     * @var array
     */
    public $reserver_collections = array('main','config');
    /**
     * Массив подгружаемых шаблонов
     *
     * @var array
     */
    private $templates = array();
    private $styles = array();
    
    /**
     * Функция создания класса
     *
     */
    public function __construct($encoding = 'UTF-8'){
        $this->dom = new DOMDocument('1.0',$encoding);
        $this->document = $this->dom->createElement('root');
        $this->xslt = new XSLTProcessor();
        foreach ($this->reserver_collections as $collection){
            $this->createCollection($collection);
        }
    }
    
    /**
     * Функция создания новой коллекции
     *
     * @param string $name
     * @param mixed $template
     */
    public function createCollection($name,$template = false, $style = false){
        if ($template === true){
            // выбираем шаблон из директории элементов
            $this->templates[] = dir_tpl_elements.$name.'.xslt';
        }elseif ($template == true){
            // указанный шаблон
            $this->templates[] = $template;
        }
        
        if ($style === true){
            // выбираем шаблон из директории элементов
            $this->styles[] = dir_css_elements.$name.'.css';
        }elseif ($style == true){
            // указанный шаблон
            $this->styles[] = $style;
        }
        $this->collections[$name] = new mod_templates_collection($name,$this->dom,$this->document);
        // Создает алиас коллекции вида cl_коллекция и возвращает ссылку на нее
        return $this->{'cl_'.$name} = $this->collections[$name];
    }
    
    /**
     * Отчистить коллекцию
     *
     * @param string $name
     */
    public function clearCollection($name){
        $this->collections[$name] = new mod_templates_collection($name,$this->dom,$this->document);
    }
    
    /**
     * Удалить коллекцию
     *
     * @param string $name
     */
    public function deleteCollection($name){
        // удаляем из массива
        unset($this->collections[$name]);
        // удаляем алиас
        unset($this->{'cl_'.$name});
    }
    
    /**
     * Функция производит XML/XSLT трансформацию, подключение
     * дополнительных шаблонов
     *
     * @param string $template
     */
    public function release($template){
        /* получаем данные из коллекций */
        foreach ($this->collections as $collection){
            $collection->release();
        }
        // добавляем в основное дерево
        $this->dom->appendChild($this->document);
        
        // проверяем наличие выбранного шаблона
        if (!file_exists($template)) die('Не найден основной шаблон '.$template);
        // выбираем данные из файла
        $xslt_data = file_get_contents($template);

        $xslt = new DOMDocument();
        
        if (!@$xslt->loadXML($xslt_data)){
            die('Ошибка при загрузке шаблона');
        }
        /* Новая работа с шаблонами */
        $xpath = new DOMXPath($xslt);
        $stylesheet = $xpath->query('//xsl:stylesheet')->item(0);
        
        foreach ($this->templates as $tpl){
            if (!file_exists($tpl)) die ('Не найден шаблон '.$tpl);
            $include = $xslt->createElementNS('http://www.w3.org/1999/XSL/Transform','xsl:include');
            $includeEl = $stylesheet->insertBefore($include,$stylesheet->childNodes->item(0));
            $includeEl->setAttribute('href',$tpl);
        }
        
        $styles = null;
        foreach ($this->styles as $css){
            $styles .= "@import url($css); \n";
        }
        /* (NEW!) Работа со стилями css */
        $head = $xpath->query('//xsl:stylesheet/xsl:template/html/head')->item(0);
        $incCss = $xslt->createElement('style');
        $incCssData = $xslt->createCDATASection("\n<!-- \n$styles -->\n");
        $incCss->appendChild($incCssData);
        $head->appendChild($incCss);
                
        if (!$this->xslt->importStylesheet($xslt)){
            die('Ошибка при импортировании шаблона');
        }
        if (!$data = $this->xslt->transformToXml($this->dom)){
            die('Ошибка при трансформации');
        }else{
            // вывод данных
            echo $data;
        }
            
    }
}

/**
 * Вспомогательный класс, описывающий коллекцию данных
 * и работу с ними
 *
 */
class mod_templates_collection{
    /**
     * Экземпляр класса DOMDocument
     *
     * @var DOMDocument
     */
    private $dom;
    /**
     * Корневой элемент (root)
     *
     * @var DOMElement
     */
    private $document;
    /**
     * Родительский элемент
     *
     * @var DOMElement
     */
    public $owner;
    
    /**
     * Имя коллекции
     *
     * @var string
     */
    public $name;
    
    /**
     * Функция создания коллекции
     *
     * @param string $name
     * @param DOMDocument $dom
     * @param DOMNode $owner
     */
    function __construct($name,DOMDocument $dom,DOMNode $owner){
        $this->name = $name;
        $this->dom = $dom;
        $this->owner = $owner;
        // создаем корневой элемент коллекции
        $this->document = $dom->createElement($name);
    }
    
    /**
     * Закончить работу с коллекцией и вернуть результат работы
     *
     */
    function release(){
        $this->owner->appendChild($this->document);
    }
    
    /**
     * Функция создает новый узел
     *
     * @param string $name
     * @param string $value
     */
    function createNode($name,$value){
        $node = $this->dom->createElement($name);
        // все данные записываем в CDATA
        $value = $this->dom->createCDATASection($value);
        $node->appendChild($value);
        // добавляем узел к документу
        $this->document->appendChild($node);
    }
    
    /**
     * Добавить массив к коллекции
     *
     * @param string $name
     * @param array $array
     * @param DOMElement $rootNode
     * @param boolean $return
     * @return DOMElement
     */
    public function append_array($name,$array,$rootNode = false, $return = false){
        $dom = $this->dom;
        $node = $rootNode ? $rootNode : $dom->createElement($name);
        foreach ($array as $fname=>$fvalue){
            if (!is_int($fname) and !is_array($fvalue)){
                // если это обычный элемент асоциативного массива
                $fnode = $dom->createElement($fname);
                $fdata = $dom->createCDATASection($fvalue);
                $fnode->appendChild($fdata);
                
                $node->appendChild($fnode);
            }elseif (is_array($fvalue)){
                // если ключ числвой - переименовываем элемент
                if (is_int($fname)) $fname = 'row';
                // если элемент является массивом
                // рекурсивно вызвываем функцию
                $fnode = $this->append_array($fname,$fvalue,false,true);
                
                $node->appendChild($fnode);
            }elseif (!is_array($fvalue) and is_int($fname)){
                // если 
                $fnode = $dom->createElement('value');
                $fdata = $dom->createCDATASection($fvalue);
                $fnode->appendChild($fdata);
                
                $node->appendChild($fnode);
            }
        }
        if ($return) return $node; else $this->document->appendChild($node);
    }
    
    /**
     * Добавить DataSet к коллекции
     *
     * @param string $name
     * @param DataSet $ds
     */
    public function append_dataSet($name,DataSet $ds){
        $this->append_array($name,$ds->data);
    }
}
?>


index.php

Код

<?php
/* config */
define('dir_tpl_elements','templates/elem/');
define('dir_tpl_files','templates/');
define('dir_tpl_modules','templates/modules/');
define('dir_css_elements','templates/css/');
$standart_template = dir_tpl_modules.'common.xslt';

/* include */
include_once('modules/mod_templates.php');

/* operations */
$tpl = new mod_templates();

/* module operations */
$tpl->createCollection('awers',true,true);
$tpl->createCollection('awersx',false,true);

/* release */
$tpl->release($standart_template);
?>


templates/elem/awers.xslt
Код

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/" name="awers">
    Привет, я awers на UTF-8!
</xsl:template>
</xsl:stylesheet>



templates/modules/common.xslt

Код

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8"/>
<xsl:template match="/">
<html>
    <head>
        <title>My Title</title>
    </head>
    <body><xsl:call-template name="awers" /></body>
</html>
</xsl:template>
</xsl:stylesheet>

PM MAIL WWW ICQ Skype   Вверх
GeneralElectric
Дата 25.2.2008, 01:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 797
Регистрация: 11.1.2008

Репутация: 13
Всего: 16



XML/XSL не угодили тем, что в них лежит китайская лапша - html перемешан с кодом, в большинстве случаев XSL кода больше, чем HTML. Как следствие, требуется отдельный программист на проект. Яндекс может себе это позволить. Другие обходятся решениями более гибкими.
PM MAIL   Вверх
awers
Дата 25.2.2008, 01:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1465
Регистрация: 22.3.2006
Где: Россия, Таганрог

Репутация: 21
Всего: 31



А как же генерация самих блоков? Или там все по взмаху волшебной палочки? Или пхп программист стоит дешевле чем HTML верстальщик со знанием XSL?
PM MAIL WWW ICQ Skype   Вверх
GeneralElectric
Дата 25.2.2008, 01:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 797
Регистрация: 11.1.2008

Репутация: 13
Всего: 16



Видимо, дешевле =)
Вообще, популярнос шаблонов-лапши, таких, как XSLt или Смарти, сравнима с популярностью шлочных шаблонов. Так что я не возьмусь судить ,какой подход лучше, а какой хуже. Видимо, у всех есть свои положительные стороны.
Другое дело, что XSLT, как верно было замечено, вносит дополнительное усложнение в среду разработки ,и не всегда это выгодно
PM MAIL   Вверх
awers
Дата 25.2.2008, 01:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1465
Регистрация: 22.3.2006
Где: Россия, Таганрог

Репутация: 21
Всего: 31



Мой последний заказчик - дизайнер. Он меня чуть не расцеловал когда я ему показал знакомые, почти ХТМЛ исходники. Теперь сам вкуривает что как и жутко доволен. Если человек чайник - ему и с   <!-- BEGIN blocks-left --> не справится. А XSLT дает явные приемущества, как по контролю ошибок в "десигн тайм" так и в "ран тайм".
PM MAIL WWW ICQ Skype   Вверх
GeneralElectric
Дата 25.2.2008, 01:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 797
Регистрация: 11.1.2008

Репутация: 13
Всего: 16



Ну, возможно, ты и прав - все дело в субьективных ощущениях конкретных людей. кому-то нравится обилие кода в шаблоне, кому-то - нет.
правда, следует отметить, что прошлый проект "знакомых, почти ХТМЛ исходников" - ColdFusion - тихо скончался в нищете и забвении.

По поводу же явных приемуществ по контролю ошибок я с удовольствием выслушаю конкретные факты.
Думаю, остальным тоже будет интересно
PM MAIL   Вверх
awers
Дата 25.2.2008, 01:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1465
Регистрация: 22.3.2006
Где: Россия, Таганрог

Репутация: 21
Всего: 31



я только начал вырабатывать концепцию, но смысл следующий: необходимо введение своего пространства имен, на нем собирать логику. это будет кратно быстрее смарти. над кешами я даже не начинал думать. вполне возможно что в Винград ЦМС войдет уже доработанная версия
PM MAIL WWW ICQ Skype   Вверх
GeneralElectric
Дата 25.2.2008, 01:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 797
Регистрация: 11.1.2008

Репутация: 13
Всего: 16



Я тут решил машину собрать. Трехколесную. У трехколесных устойчивость выше. Конкретные факты - я пока ещё не думал, но собираюсь поркасить в зеленый цвет - должна получиться быстрее формулы 1.

Все ясно.
PM MAIL   Вверх
awers
Дата 25.2.2008, 01:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1465
Регистрация: 22.3.2006
Где: Россия, Таганрог

Репутация: 21
Всего: 31



Ты посмотрел мой пример?
PM MAIL WWW ICQ Skype   Вверх
CyClon
Дата 25.2.2008, 09:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 838
Регистрация: 3.12.2005

Репутация: 3
Всего: 4



awers, заинтриговал конечно, но все-равно мой вариант более простой для верстальщика.

Мне понравилось XSLT в твоем примере, гибко так. Но пока остановлюсь на своем варианте, ибо вообще с XML не дружу и не понимаю его смысл, как когда-то ООП smile

ЗЫ: Результат обрабоки тех двух шаблонов какой будет?

Добавлено через 2 минуты и 25 секунд
P.S. Может даст кто ссылочку, где можно побольше почитать о взаимодействии XML/XSLT с PHP?


--------------------
user posted image
PM   Вверх
GeneralElectric
Дата 25.2.2008, 09:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 797
Регистрация: 11.1.2008

Репутация: 13
Всего: 16



Э, нет. Так не пойдет.
Вы, ребятки, не тестовыми шаблонами меряйтесь, а боевыми.

Какой результат тех двух шаблонов - это и так ясно: такая же тестовая рыба.
А нарисуйте-ка, оба, вывод строки навигации, вот, хотя бы, как в этом форуме:
« Первая ... 3 4 [5] 6 7 ... Последняя » 

Вот и посмотрим, чего на самом деле стоят оба подхода =)

PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0602 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.