Zend Framework: Xsl И Самосериализация Представлений

Перевод статьи Zend Framework: XSL и самосериализующиеся представления Автор: Паскаль Опиц Я давно утверждал, что фреймворки MVC должны использовать стили XSL вместо встроенного PHP-кода и тому подобного.

Вот почему я собрал небольшое доказательство концепции Zend Framework, где представления файлов имеют форму шаблона XSL, а представление сериализуется в XML для рендеринга.



Базовая структура MVC

Я только что создал демонстрационный макет, используя стандартную структуру MVC из Zend_Controller:
|-приложение |---по умолчанию |-----контроллеры |-----модели |-----просмотры |-------фильтры |-------помощники |-------скрипты |---------индекс |---------тест |-библиотека |---демо |---zendframework_1.6.2 |-вебрут
Конечно, теперь нам нужен загрузочный файл:
  
  
  
  
  
  
   

set_include_path('.

' .

PATH_SEPARATOR .

'.

/library/zendframework_1.6.2/' .

PATH_SEPARATOR .

'.

/library/demo/' .

PATH_SEPARATOR .

'.

/application/default/controllers' .

PATH_SEPARATOR .

get_include_path()); require_once('Zend/Loader.php'); Zend_Loader::loadClass('Zend_Controller_Front'); Zend_Loader::loadClass('Zend_Controller_Action_Helper_ViewRenderer'); $frontController = Zend_Controller_Front::getInstance(); $frontController->setControllerDirectory(array( 'default' => '.

/application/default/controllers', )); require_once 'View_Xslt.php'; $view = new View_Xslt; $options = array(); $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view, $options); $viewRenderer->setViewSuffix('xsl'); Zend_Controller_Action_HelperBroker::addHelper($viewRenderer); $frontController->dispatch();

Обратите внимание, что я представил новый viewRenderer и объект представления, который вызывается из View_Xslt.php и находится в папке библиотеки/демо.

Я также установил суффикс представления для XSL. Можно загрузить ZIP-файл, содержащий всю демонстрационную версию (за исключением файлов Zend Framework).

Здесь .



Просмотры (ПРОСМОТР)

Объект View должен быть производным от класса, расширяющего Zend_View_Abstract. Рендеринг представления происходит в методе _run, и файл представления будет передан в качестве первого аргумента.

Однако этот аргумент должен быть доступен с помощью func_get_arg, иначе мы столкнемся с аккуратным сообщением об ошибке, что наш оператор несовместим с Zend_View_Abstract. Чтобы мой объект View впоследствии мог самосериализоваться, я также добавил сериализатор в метод магического конструктора, а также добавил частную функцию, которая сериализует представления в XML с помощью только что созданного сериализатора.



require_once('Serializer.php'); class View_Xslt extends Zend_View_Abstract { private $serializer; private $rootName; public function __construct($data = array()) { $this->serializer = new Serializer(); parent::__construct($data); } public function setRootName($name) { $this->rootName = $name; } protected function _run() { $template = func_get_arg(0); $xslDoc = new DOMDocument(); $xslDoc->load($template); $xmlDoc = $this->toXml(); $proc = new XSLTProcessor(); $proc->importStylesheet($xslDoc); echo $proc->transformToXML($xmlDoc); } private function toXml() { $xml_str = $this->serializer->Serialize($this, $this->rootName); return $xml_str; } }



Сериализатор

Так что же делает сериализатор? Он использует Reflect( отражение ) функциональность для сериализации объектов в строку XML. Это дает нам возможность использовать обычные переменные поиска с действиями нашего контроллера, просто сказав $this-> foo = 'bar'.

Ранее я уже делал небольшой пост о сериализации XML, и представленный мной сериализатор был вдохновлен тем, что я там нашел.

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



class Serializer { private $xmlDoc; public function __construct() { $this->xmlDoc = new DOMDocument(); } public function Serialize($inst, $nodeName=null) { if(is_object($inst)) { $nodeName = ($nodeName == null) ? get_class($inst) : $nodeName; $root = $this->xmlDoc->createElement($nodeName); $this->xmlDoc->appendChild($root); $this->SerializeObject($inst, $nodeName, $root); } else if(is_array($inst)) { $nodeName = ($nodeName == null) ? get_class($inst) : $nodeName; $root = $this->xmlDoc->createElement($nodeName); $this->xmlDoc->appendChild($root); $this->SerializeArray($inst, $nodeName, $root); } return $this->xmlDoc; } private function SerializeObject($inst, $nodeName, $parent) { $obj = new ReflectionObject($inst); $properties = $obj->getProperties(); foreach($properties as $prop) { if(!$prop->isPrivate()) { $elem = $this->SerializeData($prop->getName(), $prop->getValue($inst), $parent); } } } private function SerializeArray($array, $nodeName, $parent) { foreach($array as $key => $val) { $keyStr = (is_numeric($key)) ? 'ArrayValue' : $key; $elem = $this->SerializeData($keyStr, $val, $parent); if(is_numeric($key)) { $elem->setAttribute('index', $key); } } } private function SerializeData($key, $val, $parent) { if(is_object($val)) { $propNodeName = get_class($val); $elem = $this->xmlDoc->createElement($propNodeName); $parent->appendChild($elem); $this->SerializeObject($val, $propNodeName, $parent); $elem->setAttribute('type', 'object'); } else if(is_array($val)) { $elem = $this->xmlDoc->createElement($key); $parent->appendChild($elem); $this->SerializeArray($val, $key, $elem); $elem->setAttribute('type', 'array'); } else { $elem = $this->xmlDoc->createElement($key, $val); $parent->appendChild($elem); $elem->setAttribute('type', 'property'); } return $elem; } }



Контроллер и просмотр файлов

Почти все.

Нам просто нужно несколько файлов XSL и контроллер с действиями, чтобы получить работающую демо-версию.

Первый контроллер и действие.

Я включил небольшой демонстрационный класс, чтобы мы могли увидеть сериализатор в действии:

class IndexController extends Zend_Controller_Action { public function indexAction() { $this->view->setRootName('DataObject'); $this->view->foo = 'bar'; $this->view->super = array( 'here' => 'there', 'foo' => array(1,2,'test'), ); $this->view->testObject = new DemoObject(); $this->view->testObject->var = 'testObjectVar'; } } class DemoObject {}

Просмотр файлов.

Мы могли бы создать только один, но поскольку я хотел поддерживать Zend_Layout, я не использовал xsl:import, чтобы сделать что-то подобное.



<Эxml version="1.0" encoding="ISO-8859-1"?> < xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform "> < xsl:import href=".

/layout.xsl"/> < xsl:template match="DataObject"> < xsl:apply-templates select="*" /> </ xsl:template > < xsl:template match="*"> <div> <h2>< xsl:value-of select="name()" /></h2> < xsl:apply-templates select="text()" /> < xsl:apply-templates select="*" /> </div> </ xsl:template > </ xsl:stylesheet >



<Эxml version="1.0" encoding="ISO-8859-1"?> < xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform "> < xsl:output method="xml" encoding="ISO-8859-1" omit-xml-declaration="no" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system=" http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd " indent="yes" /> < xsl:template match="/"> <html> <head> <title>Test</title> </head> <body> < xsl:apply-templates select="/*" /> </body> </html> </ xsl:template > </ xsl:stylesheet >



Результат

Вот и все! Полученная индексная страница должна дать вам что-то вроде этого:

<Эxml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd "> <html xmlns=" http://www.w3.org/1999/xhtml "> <head> <meta http-equiv="Content-Type" content="текст/html; кодировка = ISO-8859-1" /> <title>Test</title> </head> <body> <div><h2>foo</h2>bar</div> <div> <h2>super</h2> <div><h2>here</h2>there</div> <div> <h2>foo</h2> <div><h2>ArrayValue</h2>1</div> <div><h2>ArrayValue</h2>2</div> <div><h2>ArrayValue</h2>test</div> </div> </div> <div> <h2>DemoObject</h2> </div> <div><h2>var</h2>testObjectVar</div> </body> </html>




Так получилось, что я уже давно работаю с XML и для своей работы хотел использовать шаблонизатор от XSLT в ZendFramework, и это единственная статья, которую мне удалось найти, позволяющая реализовать это желание.

В результате у меня получилась простая система, где движок и набор стандартных шаблонов работали для небольших сайтов-визиток, а контент с них хранился в xml-файлах в папке data. И вся миграция с хостинга на хостинг произошла простым копированием, без головной боли с базой данных.

А опубликованная папка содержала только CSS, JavaScript и изображения.

Теги: #Zend Framework #xml #xslt #php #Zend Framework #xslt

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

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