Планируется, что первая версия, которую можно будет назвать стабильной и полностью юзабельной, появится до конца года.
Поскольку до конца года осталось менее суток, то позвольте рассказать о том, что еще удалось сделать в этом году.
XML facilities
Среди прочих задач, поставленных перед Easyweb-ом, была необходимость сделать работу с XML на стороне PHP максимально чистой, изящной, компактной и простой для понимания. В данный момент дописаны все основные методы XML-фасилитей. Описание публичных методов и небольшие примеры использования:
- XML document: github.com/nyan-cat/easyweb/wiki/class-xml
- XML node set: github.com/nyan-cat/easyweb/wiki/class-nodeset
- XML node: github.com/nyan-cat/easyweb/wiki/class-node
Как и всегда, любую дополнительную функциональность можно попросить через feature request на
Приведу пример решения одной и той же задачи на стандартном PHP DOM API, и на Easyweb XML facilities. Суть такова. Нужно загрузить файл с описанием книг, и сделать с каждой книгой следующее: обнулить цену, заменить код валюты на его написание в нижнем регистре, а также установить заданные идентификаторы для автора и категории книги (включая проверку ошибок).
Было:
<?php function replace($author_id, $category_id) { $xml = new DOMDocument(); if(!$xml->load('/var/www/html/mywebsite/xml/library.xml')) { throw new Exception('Error loading XML file'); } $xpath = new DOMXPath($xml); foreach($xpath->query('/books/book') as $book) { $price = $xpath->query('price', $book); if($price->length != 1) { throw new Exception('Node "price" should be unique for the book'); } $price->item[0]->nodeValue = 0; $currency = $price->getAttribute('currency'); if($currency) { $book->setAttribute('currency', strtolower($currency)); } else { throw new Exception('Attribute "currency" not found'); } $book->setAttribute('author_id', $author_id); $book->setAttribute('category_id', $category_id); } } ?>
Стало:
<?php function replace($author_id, $category_id) { $xml = xml::load('/xml/library.xml'); foreach($xml->query('/books/book') as $book) { $book['price'] = 0; $book['price/@currency'] = strtolower($book['price/@currency']); $book['@author_id'] = $author_id; $book['@category_id'] = $category_id; } } ?>
Easyweb XML фасилити умеют конструироваться от нативных PHP DOM resource handle, а также выдавать их пользователю через мембер-функцию ::get()
, в связи с чем можно легко интегрироваться со сторонними библиотеками, работающими через нативные PHP DOM объекты.
XPath-расширение www:paginate
www:paginate($page, $count, $size)
Функция предназначена для упрощения отрисовки статического пагинатора.
$page
— текущая страница.
$count
— общее количество страниц.
$size
— размер пагинатора.
Текущая страница отмечается атрибутом current
. На первой странице не будет ноды <previous />
, на последней — ноды <next />
.
Вызов функции www:paginate(15, 85, 10)
вернет вот такой XML:
<pages> <previous>14</previous> <page>10</page> <page>11</page> <page>12</page> <page>13</page> <page>14</page> <page current="current">15</page> <page>16</page> <page>17</page> <page>18</page> <page>19</page> <next>16</next> </pages>
Пример верстки:
<xsl:template match="/"> <xsl:apply-templates select="www:paginate(15, 85, 10)/pages/*" /> </xsl:template> <xsl:template match="previous"> <a href="/page/{.}/" class="page">← Previous</a> </xsl:template> <xsl:template match="next"> <a href="/page/{.}/" class="page">Next →</a> </xsl:template> <xsl:template match="page[@current]"> <span class="page current"><xsl:value-of select="." /></span> </xsl:template> <xsl:template match="page"> <a href="/page/{.}/" class="page"><xsl:value-of select="." /></a> </xsl:template>
Возможный результат:
Кеширование блоков
Теперь результат XSL-расширения www:xslt
можно кешировать в файлы. Для этого нужно добавить атрибут cache="true"
. Также имеется два необязательных атрибута cache-args
и cache-lifetime
, первый из которых позволяет передать в закешированный блок список простых параметров, а второй — ограничить время жизни закешированных данных. Пример использования:
<www:xslt xsl="/books.xsl" xml="book:list(author_id -> {$author_id})" args="page -> {$page}, count -> 10" cache="true" cache-args="domain -> '{$domain}'" cache-lifetime="600" />
XQuery
Первый вариант поддержки XQuery в Easyweb. На данный момент его возможности сильно ограничены: нельзя передать параметры, нельзя использовать XSL- и XPath-расширения Easyweb-а. Главная проблема сейчас заключается в том, что хорошую XQuery-библиотеку для PHP не удалось найти в принципе. Если вы можете помочь мудрым советом, то буду рад услышать его здесь: habrahabr.ru/qa/31087/
На данный момент XQuery сделан через XQuery Lite (http://phpxmlclasses.sourceforge.net/xquery_lite.html), который был сделан и заброшен его автором еще в 2002-м году. XQuery Lite выложен в репозиторий Easyweb в связи с тем, что его пришлось допилить напильником, чтобы он заработал в PHP5.
Сейчас поддержка XQuery заключается во введении XSL-расширения www:xquery
:
<div> <h1>External Resources</h1> <www:xquery src="/tpl/links.xq" /> </div>
Пользовательские XSL-расширения
Теперь пользователь может регистрировать в движке свои собственные XSL-расширения. Для своего собственного расширения нужно указать пространство имен, а также его URI. То же самое нужно сделать в XSL-шаблонах страниц. Пример регистрации XSL-расширения, реализующего некоторую обработку текста (например — какая-то своя разметка):
$www = www::create('en', 'us'); $www->register_xsl('http://supermarkup.com/about', 'sm', 'block', function($node) { $xml = new xml(); foreach($node->children() as $child) { $xml->append($xml->import($child)); } foreach($xml->query('//text()') as $text) { $parent = $text->parent(); $parent->append(supermarkup($text->value())); $parent->remove($text); } return $xml; });
Использование в шаблоне:
<?xml version="1.0" encoding="utf-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" xmlns:www="https://github.com/nyan-cat/easyweb" xmlns:sm="http://supermarkup.com/about" exclude-result-prefixes="php www sm"> <xsl:template match="/"> <sm:block> <xsl:copy-of select="message" /> </sm:block> </xsl:template> </xsl:stylesheet>
Функция-обработчик расширения работает через Easyweb XML фасилити. Она принимает на вход XML-ноду, являющуюся расширением, и возвращает либо XML-ноду, либо XML-документ, которыми будет заменена нода расширения.
Почему лучше писать пользовательские расширения, чем напрямую ковыряться в коде движка? Потому что Easyweb гарантирует (ну или почти гарантирует), что интерфейс регистрации и хендлера расширения меняться не будет, а вот недокументированные внутренности вполне могут быть перепилены.
GeoIP
В движке появилась поддержка GeoIP. Для его работы потребуется установить PHP PECL GeoIP. Поддержка GeoIP сделана через интерфейс абстрактных процедур Easyweb-а. Пример описания GeoIP-процедуры в конфиге сайта:
<procedure name="geoip:record" datasource="geoip" method="record" root="record"> <param name="host" type="string" /> </procedure>
Теперь эту поцедуру можно использовать в любом месте, где используются абстрактиные процедуры Easyweb-а: при рендере страницы, при рендере блока, при вычислении групп системы прав доступа, при вызове XPath-расширения www:query
, или же из PHP через инстанс класса Easyweb. Пример вызова:
$record = $www->query('geoip:record', array ( 'host' => $www->variable('user:ip') ));
Возможный результат:
<?xml version="1.0"?> <record> <country> <alpha2>US</alpha2> <alpha3>USA</alpha3> <name>United States</name> </country> <region>NC</region> <city>Charlotte</city> <latitude>35.206001281738</latitude> <longitude>-80.829002380371</longitude> </record>
Не забудьте, что GeoIP-базу качать нужно отдельно:
- Установка бесплатной базы: http://www.maxmind.com/en/installation?city=1
- Более подробная платная версия: http://www.maxmind.com/en/city
- Ну, или на торрентах 😉
Полнотекстовый и фасетный поиск
Появилась первая пробная версия полнотекстового и фасетного поиска. Поиск выполняется через Apache Solr (http://lucene.apache.org/solr/). Для использования поиска потребуется установить Java, Servlet container (например — Tomcat или Jetty), сам Solr, а также PHP PECL SolrClient. Простая и доступная статья по установке Solr-а на CentOS: http://blog.nexcess.net/2011/12/30/installing-apache-solr-on-centos/.
Как и в случае GeoIP, Solr-поиск реализован через абстрактные процедуры Easyweb, которые можно использовать в разных подсистемах движка. Пример конфига:
<datasource name="metadata" type="solr" server="localhost" port="8080" url="/solr/" username="admin" password="samplepassword" /> <!-- ... --> <procedure name="guestbook:add" datasource="guestbook" core="guestbook" method="add"> <param name="author_id" type="natural" /> <param name="message" type="author" /> <param name="host" type="ipv4" /> </procedure> <!-- ... --> <procedure name="guestbook:list" datasource="guestbook" core="guestbook" method="query" root="messages" item="message"> *:* </procedure>
Пока что конфигурить Solr нужно самостоятельно. В будущем планируется сделать генератор схемы Solr-а налету.
Заключение
Итак, в движке реализованы все основные функции уровня ядра, котрые были ранее запланированы. В более долгосрочных планах остаются LL(1)-парсеры, ORM-система и фреймворк для полнодуплексного общения клиента и сервера.
Планы на начало следующего года — заняться переездом одного Большого® Коммерческого© Сайта™, использующего все функции Easyweb-а, на новую версию движка, параллельно с чем будут устраняться обнаруженные ошибки.
С большой радостью приму ваши фичреквесты, багрепорты, и просто вопросы по установке и использованию Easyweb-а.
С Новым годом!
ссылка на оригинал статьи http://habrahabr.ru/post/164397/
Добавить комментарий