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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Шаблонный движок, DOM vs Array 
:(
    Опции темы
awers
Дата 25.3.2008, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Есть шаблонный движок, XML+XSLT. 

Суть заключается что документ разбит на Коллекции, в которых есть данные. 
Все методы класса абстрагируют DOM, который является недрами движка. 

Как вы считаете, стоит ли переделать все на массивы. 
Давайте подойдем к этому не только с точки зрения скорости (что немаловажно, но всеже), а с точки зрения удобности (к примеру в процессе работы со своим движком я могу применять XPath, а с массивами я уже лишусь этой возможности)

Вот один из билдов
Код

<?php

/**
 * Модуль для работы с XSLT шаблонами
 *
 * @author awers
 * @copyright DSE 2008
 * @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();
    private $doc_title = false;
    
    /**
     * Функция создания класса
     *
     * @param string $encoding
     */
    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
     * @param mixed $style
     */
    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});
    }
    
    public function addStyle($file){
        $this->styles[] = $file;
    }
    
    /**
     * Функция производит XML/XSLT трансформацию, подключение
     * дополнительных шаблонов
     *
     * @param string $template
     * @param string $style
     * @param string $title
     */
    public function release($template, $style = false, $title = false){
        /* получаем данные из коллекций */
        foreach ($this->collections as $collection){
            $collection->release();
        }
        
        /* Добавление стиля */
        if ($style){
            $this->addStyle($style);
        }
        
        /* Установка титла документа */
        if ($title){
            $this->cl_config->createNode('title',$title);
        }
        
        // добавляем в основное дерево
        $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('Ошибка при загрузке шаблона');
        }
        
        /* Новая работа с шаблонами */
        if (count($this->templates) > 0){
            $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);
            }
        }
        
        /* (NEW!) Работа со стилями css */
        if (count($this->styles) > 0){
            $styles = null;
            foreach ($this->styles as $css){
                $styles .= "@import url($css); \n";
            }
            $head = $xpath->query('//xsl:stylesheet/xsl:template/html/head');
            if($head->length > 0){
                $head = $head->item(0);
                $incCss = $xslt->createElement('style');
                $incCssData = $xslt->createCDATASection("\n<!-- \n$styles -->\n");
                $incCss->appendChild($incCssData);
                $head->appendChild($incCss);
            }else{
                trigger_error('Не найдена шапка документа /html/head',E_USER_NOTICE);
            }
        }
        
        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);
    }
}
?>


Это сообщение отредактировал(а) awers - 25.3.2008, 18:47
PM MAIL WWW ICQ Skype   Вверх
flashaa
Дата 25.3.2008, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 19
Всего: 25



awers, а пример работы можно?
PM MAIL   Вверх
awers
Дата 25.3.2008, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



flashaa, самый простой или с использованием всего функционала?
PM MAIL WWW ICQ Skype   Вверх
mishaSL
Дата 25.3.2008, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1046
Регистрация: 10.1.2007
Где: Санкт-Петербург

Репутация: 19
Всего: 54



awers, не много не понял. А зачем вам переделывать все на массивы? Какой из этого смысл?

Пример работы с использованием того функционала, который вас не устраивает, если вы хотите его переделать...


--------------------
Лучший способ научиться программированию - это посмотреть как это делают другие...
PM MAIL   Вверх
awers
Дата 25.3.2008, 19:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



mishaSL, просто задумался о нагрузке и необоснованных затратах на работу с DOM. В этом собственно и вопрос. 

А что в целом скажите? Такой шаблонный движек имеет право на жизнь? Предусмотрел все, начиная от авто-инклюда шаблонов (xsl-include сам прописывается в шаблон), до CSS инклюда
PM MAIL WWW ICQ Skype   Вверх
Smith
Дата 25.3.2008, 20:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: 1
Всего: 2



если думать о быстродействии, то брать за шаблонизатор РНР)

Это сообщение отредактировал(а) Smith - 25.3.2008, 20:48
PM MAIL   Вверх
awers
Дата 25.3.2008, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Smith, а ты посмотри на это с точки зрения безопасности и рациональности. Дизайнер со знанием пхп - раз, давать недры пхп в руки дизайнера - увольте
PM MAIL WWW ICQ Skype   Вверх
flashaa
Дата 26.3.2008, 11:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 19
Всего: 25



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

Это сообщение отредактировал(а) flashaa - 26.3.2008, 11:59
PM MAIL   Вверх
mishaSL
Дата 26.3.2008, 12:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1046
Регистрация: 10.1.2007
Где: Санкт-Петербург

Репутация: 19
Всего: 54



Цитата(awers @  25.3.2008,  19:35 Найти цитируемый пост)
mishaSL, просто задумался о нагрузке и необоснованных затратах на работу с DOM. В этом собственно и вопрос. 

ИМХО, вариант с XML+XSL мне нравится, да и быстодействие от этого не сильно страдает, если кеширование сделать нормально.


--------------------
Лучший способ научиться программированию - это посмотреть как это делают другие...
PM MAIL   Вверх
awers
Дата 26.3.2008, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



mishaSL, есть какие-то мысли/идеи по кешированию? буду благодарен )
PM MAIL WWW ICQ Skype   Вверх
IZ@TOP
Дата 26.3.2008, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 44
Всего: 73



На мой взгляд:

1. XSLT vs Smarty, PTemplate and etc

Схема XML+XSLT более трудна для понимания, строга и требовательна к ресурсам. Тем не менее, если мы стремимся к идеологии разделения логики, данных и представления (взять тот же MVC), хотим оградить/обезопасить или просто унифицировать систему - мы берем за основу XML и XSLT. Тем более, что уже давным-давно вопрос распределения нагрузки не стоит в тупике и производители железа предоставляют каждый день что-то новое и более производительное (нет на денег/ресурсов? - проект не удался).

Smarty, как шаблонный (или компонентный, как некоторые используют) движок, лично мне не нравится, ввиду своей громоздкости и устарелости. Для небольших и средних проектов - да, это то что нужно; для простоты и удобства (на первый взгляд) написания, когда нет времени разбираться в технологиях, искать решения, думать и строить собственную архитекуру, мы берем простой и универсальный Smarty. Мы его берем, потому что он зарекомендовал себя на этом поприще.

Есть и другие шаблонизаторы. Есть написанный собственноручно. Но все это не идет в сравнение с гигантом Smarty и утвержденным W3C концорциумом стандартом XSLT, который применяется в производственных масштабах и все больше привлекает Web-разработчиков (это можно было бы сказать лет пять назад). 
Вот так. Больше и сказать-то нечего.

Есть еще вариант. PlainPHPView. Говорить о нем не буду, по названию все понятно.


2. Кеширование.

Понятное дело, что, многие шаблонизаторы позволяют кеширование на уровне файловой системы (в т.ч. Smarty). Но как организовать кеширование в схеме XML+XSLT? Я так же когда-то задумывался над этим вопросом.
Были мысли сохранять отдельные ветви с данными в разных файлах, после собирать узлы из них. Были варианты использовании базы для их хранения. Было еще много каких мыслей; детский сад, одним словом.

Самым простым ответом на этот вопрос является Memcache. Ведь незачем изобретать велосипед, верно? Можно вопсользоваться мудростью и опытом разработчиков livejournal.  Возможно многие слышали, а кто-то его уже давно использует. Кто-то эффективно, кто-то не очень. 
Вот его я и предлагаю использовать. Кеширование на уровне данных модели в самой логике.

Спасибо за внимание.

Это сообщение отредактировал(а) IZ@TOP - 26.3.2008, 17:48


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
awers
Дата 26.3.2008, 17:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



IZ@TOP, большое спасибо. 

Смарти мне жутко не нравится, значит буду копать в сторону memcache
PM MAIL WWW ICQ Skype   Вверх
IZ@TOP
Дата 26.3.2008, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 44
Всего: 73



awers, если не планируется масштабирование системы, разнделение по серверам, можно и XCache заюзать.

Это сообщение отредактировал(а) IZ@TOP - 27.3.2008, 13:43


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
awers
Дата 27.3.2008, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



IZ@TOP, посмотрел. Но таких нагрузок нет, что бы пришлось ставить такой кешер. Куда проще memcache
PM MAIL WWW ICQ Skype   Вверх
IZ@TOP
Дата 27.3.2008, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Панда-бир!
****


Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес

Репутация: 44
Всего: 73



awers, XCache как раз попроще будет (и чуть быстрее). Memcache куда более интересен в ситуации, когда у тебя распределенная система. К примеру - прокси-балансер, который распределяет нагрузку на несколько серверов frontend/backend.

Это сообщение отредактировал(а) IZ@TOP - 27.3.2008, 13:46


--------------------
Один из розовых плюшевых-всадников апокалипсиса... очень злой...

Семь кругов ада для новых элементов языка
Мои разрозненные мысли
PM MAIL WWW ICQ Skype GTalk   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "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.0593 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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