Перевод статьи Zend Framework: XSL и самосериализующиеся представления Автор: Паскаль Опиц Я давно утверждал, что фреймворки MVC должны использовать стили XSL вместо встроенного PHP-кода и тому подобного.
Вот почему я собрал небольшое доказательство концепции Zend Framework, где представления файлов имеют форму шаблона XSL, а представление сериализуется в XML для рендеринга.
Базовая структура MVC
Я только что создал демонстрационный макет, используя стандартную структуру MVC из Zend_Controller:|-приложение |---по умолчанию |-----контроллеры |-----модели |-----просмотры |-------фильтры |-------помощники |-------скрипты |---------индекс |---------тест |-библиотека |---демо |---zendframework_1.6.2 |-вебрутКонечно, теперь нам нужен загрузочный файл:
Обратите внимание, что я представил новый viewRenderer и объект представления, который вызывается из View_Xslt.php и находится в папке библиотеки/демо.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();
Я также установил суффикс представления для 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
-
Внедрение Корпоративного Linux В Приватбанке
19 Oct, 24 -
Microsoft Обновила Свою Домашнюю Страницу
19 Oct, 24 -
Рутрекеру 9 Лет.
19 Oct, 24 -
Клавиатура, Идея, Две Руки
19 Oct, 24 -
Что Вам Мешает Работать?
19 Oct, 24