Автор: Pascal Opitz
Я давно утверждал, что фраемворки MVC должны использовать стили XSL вместо встроенного PHP кода и прочего. Вот почему я постучал вместе немного доказательство концепции Zend Framework, где представления файлов в виде XSL шаблона, а представление сериализует себя в XML для рендеринга.
Базовая структура MVC
Я только что создал демо-макет, используя стандартную структуру MVC из Zend_Controller:
|-application
|—default
|——controllers
|——models
|——views
|——-filters
|——-helpers
|——-scripts
|———index
|———test
|-library
|—demo
|—zendframework_1.6.2
|-webroot
Конечно, теперь нам нужен загрузочный файл:
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 и находится в папке library/demo. Также я установил суффикс представления для XSL.
ZIP файл, содержащий все демо (без учета Zend Framework файлов) можно скачать здесь.
Представления (VIEW)
View объект должен быть получен из класса, который расширяет Zend_View_Abstract. Рендинг View происходит в методе _run, и файл представления будет передан в качестве первого аргумента. Однако, этот аргумент должен быть доступен с func_get_arg, в противном случае мы сталкиваемся с аккуратным сообщением об ошибке, что наше заявление несовместимо с Zend_View_Abstract.
Для того, чтобы мой View объект само-сериализации позже, я также добавил Serializer в магическом методе конструктора, плюс я добавил приватной функции, которая сериализует представления в XML с использованием Serializer, который мы только что создали.
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; } }
Сериализатор (Serializer)
Так что же это сериализатор делает? Он использует Отражение(рефлексию) функциональности для сериализации объектов в XML строку. Это дает нам возможность использовать нормальные переменные для просмотра с помощью наших контроллеров действий(controller actions), просто говоря $this->foo = ‘bар’.
Я делал быстрый пост 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 {}
Файл(ы) View. Мы могли бы создать только один, но потому, что я хотел подерживать 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="text/html; charset=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 и картинки.
ссылка на оригинал статьи http://habrahabr.ru/post/166631/
Добавить комментарий