- Что такое CompleXml Framework
- Требования
- Установка и настройка CompleXml
- Особенности и отличия
- Начало работы
- Конфигурирования CompleXml Framework
- Работа с базами данных
- Кеширование
- Множества данных (Сессии, Куки, Request, POST, GET)
- Авторизация и права доступа
- Ведение журналов (Logs)
- Производительность CompleXml
CompleXml Framework - быстрый, расширяемые, производительный, открытый php framework. Предназначен для быстрой разработки веб приложений с использованием языка php 5 и xml технологий, таких как xslt, xpath, xinclude. CompleXml бесплатен и имеет открытый исходный код, распространяется по лицензии new BSD
Для работы CompleXml требуется PHP >= 5.2.3, с поддержкой расширений libxml, xsl, xmlWriter, DOM/XML. Для работы с режиме командной строки необходимо расширение readline.
Для установки CompleXml необходимо скачать архив на сайте http://complexml.org или получите копию репозитория svn
svn co http://complexml.googlecode.com/svn/trunk complexml
после получения кода фрейморка, поместите содержимое директории lib/ в директорию, указаную в опции include_path ваших настроек php или добавте к настройкам этой опции путь к CompleXml в php.ini, так же возможна установка include_path перед выполнением скрипта, для этого перед каждым запуском скрипта выполняйте
set_include_path(get_include_path().PATH_SEPARATOR .'/path/to/CompleXml/lib');
От аналогов CompleXml отличают ряд особенностей:
- Производительный, расширяемый фреймворк
- Построен на шаблоне проектирования MVC (Model - View - Controller), View часть фреймворка изолирована от модели и контролера за счет использования технологии XML+XSL.
- Активное использование интроспекции языка для решения ряда задач
- Гибкая система кеширования
- Поддержка xsl преобразований в браузере пользователя.
- "Честный" AJAX (asynchronous JavaScript + XML), ответы от сервера приходят в виде XML
- Компоненты для работы с командной строкой, включая компоненты для создания многопоточных приложений
Для быстрого начала работы с CompleXml, выполните команду из директории ./bin
./cx create project firstproject
Эта комманда создаст в текущем рабочем каталоге проект под названием firstproject, если вы хотите скопировать в lib директорию проекта копию фреймворка, выполните команду
./cx create project firstproject --with-lib
Для того, чтобы указать другую директорию, в которой нужно создать проект, используйте комманду:
./cx create project firstproject --dir /path/to/workspace
Примечание: в *NIX системах вы можете использовать команду alias для упрощения работы с командной строкой
alias cx=path/to/CompleXml/bin/cx
После создания проекта, в рабочей директории создается проект, имеющий такую структуру:
./firstproject #--> корневая директория проекта (APPLICATION_HOME)
application #--> директория, с рабочими файлами проекта
controllers #--> контроллеры
indexController.php #--> файл, содержащий контроллер, срабатывающий по умолчанию
errorController.php #--> файл, содержащий контроллер срабатывающий при ошибках
configs #--> директория, для рабочей конфигурации проекта
models #--> директория с моделями проекта
~locales #--> ссылка на директорию ./firstproject/public/locales, ссылка нужна для большей логичности структуры приложения, ее наличие не обязательно
~templates #--> ссылка на директорию ./firstproject/public/templates, ссылка нужна для большей логичности структуры приложения, ее наличие не обязательно
cache #--> директория для кеша проекта
configs #--> глобальная конфигурация проекта
main.ini.php #--> файл основных настроек проекта
cli.ini.php #--> файл настроек задач командной строки
lib #--> директория, содержащая библиотеки проекта
logs #--> директория журналов проекта
public #--> DocumentRoot сервера
templates #--> директория для шаблонов
index
index.xsl
error
notfound.xsl
locales #--> директория для локализаций
index.php #--> DefaultIndex файл
.htaccess
cx #--> скрипт для управления проектом, для *NIX систем
cx.php #--> php скрипт для управления проектом
cx.bat #--> скрипт для управления проектом, для систем семейства windows
Примечание: ссылки на директории templates и locales в applications создаются только в *NIX системах
Для работы этого проекта, необходимо настроить веб сервер так, чтобы рабочая директория сервера (DocumentRoot) была направлена в firstproject/public
Конфигурация проекта находится в папке firstproject/configs, главный файл с настройки main.ini.php:
<?php
define('APPLICATION_HOME', dirname(dirname(__FILE__))); //путь к главной директории проекта
//добавляет к include_path, директории lib проекта
set_include_path(get_include_path().PATH_SEPARATOR.APPLICATION_HOME.DIRECTORY_SEPARATOR.'lib');
//подключает класс-загрузчик, который используется для подключения остальных классов фреймворка
require_once 'CompleXml/Loader.php';
//регистрирует autoload метод, при помощи которого автоматически подключаются остальные классы
spl_autoload_register(array('CompleXml_Loader', 'autoload'));
...
После определения константы APPLICATION_HOME, подключения загрузчика и установки autoload метода, можно установить свои параметры, для этого нужно использовать класс CompleXml_Config:
//установка массива параметров
CompleXml_Config::setArray(
array(
'foo'=>'bar',
'test'=>'test'
)
);
$foo = CompleXml_Config::get('foo'); //вернет "bar"
//установка одиночного параметра
CompleXml_Config::set('param', 'value');
Вот у вас уже установлен фреймворк, развернут первый проект, можно приступить к работе.
Рассмотрим как в CompleXml предлагается обрабатывать запрос от браузера пользователя и отдавать ответ.
Первым делом после получения запроса находится маршрутизатор (наследник CompleXml_Router) который соответствует параметрам запроса, для указания параметров в CompleXml используются DocBlock нотации. Для примера рассмотрим простой маршрутизатор, который создается вместе с проектом:
require_once '../configs/main.ini.php';
/**
* параметр, указывающий фреймворку на домен, для которого
* предназначен этот маршрутизатор
* @domain {enter your public domain}
*/
class PublicRouter extends CompleXml_Router
{
}
/**
* для указания нескольких доменов,
* укажите несколько параметров @domain
* @domain firstproject.dev
* @domain www.firstproject.dev
*/
class DevRouter extends PublicRouter
{
//метод вызывающийся после старта маршрутизатора
public function init()
{
CompleXml_Config::setSettings('Output_Xml',
array('only_xml'=>$this->Request->getBool('xml'))
);
}
}
CompleXml_Application::run(); //запуск приложения
При обработке запроса, обработчик фреймворка CompleXml будет находить из всех объявленных наследников CompleXml_Router, выделение разных маршрутизаторов для разных доменов позволяет удобно и просто разделять логику работы для публичных, тестовых и серверов разработки. Если маршрутизатор не был найден, будет использоваться CompleXml_Router_Default.
Примечание: при поиске нужного маршрутизатора, первыми проверяются те, которые первые объявлены, это стоит учитывать при высоко нагруженных проектах, и объявлять раньше те маршрутизаторы, которые чаще вызываются и имеют более точные критерии в параметре @domain.
Примечание: поиск маршрутизатора происходит до первого объявленного маршрутизатора, удовлетворяющего условиям.
После нахождения маршрутизатора домена, происходит поиск метода-маршрута, который срабатывает на определенный @uri, в
CompleXml_Router определен маршрут по умолчанию:
class CompleXml_Router{
...
/**
* @uri /
* @uri /<controller:w>
* @uri /<controller:w>/<action:w>
*/
public function defaultRoute($controller, $action)
{
if (is_null($controller)){
$controller = 'index';
}
if (is_null($action)){
$action = 'index';
}
return array(
'controller'=>$controller,
'action'=>$action
);
}
...
}
Поиск маршрута происходит по параметру @uri в DocBlock методов маршрутизатора. После нахождения метода-маршрута, создается объект маршрутизатора, выполняется метод init() и выполняется метод-маршрут. Параметрами для маршрута могут быть переменные полученные из DocBlock аннотаций, например
/**
* @uri /<year:d>-<month:d>-<day:d>
*/
public function myRoute( $year, $month, $day)
{
$controller = 'calendar';
$action = 'show';
return array(
'controller'=>$controller,
'action'=>$action
);
}
Порядок параметров метода не играет роли, важно что-бы имя параметра метода совпадало с переменной шаблона <year:d> - $year. Все найденные в аннотациях переменные будут доступны в объекте Request, объект Request объявлен в CompleXml_Router и доступен во всех маршрутизаторах:
/**
* @uri /<year:d>-<month:d>-<day:d>
* пример произвольного порядка параметров в методе-маршруте
*/
public function myRoute( $month, $day, $year)
{
$controller = 'calendar';
$action = 'show';
if ($year==$this->Request->getInt('year')){
//код выполнится, так как все переменные из аннотаций попадают в $this->Request;
}
return array(
'controller'=>$controller,
'action'=>$action
);
}
Переменные аннотаций оформляются следующим образом <имя:тип>, в данный момент поддерживается 2 типа: w - любые буквенные символы и d - любые цифры.
Основная задача маршрутизатора - определить контролер и действие контролера, для того чтобы задать контроллер есть несколько способов это сделать - в параметре @uri можно задать шаблоны поиска переменных, например /<controller:w>/<action:w>; в методе-маршруте вернуть ассоциативный массив, содержащий 'controller' и 'action' значения; установить в объекте Request значения 'controller' и 'action', например
...
$this->Request->setValue('controller', 'index');
$this->Request->setValue('action', 'index');
...
Примечание: по умолчанию, маршрутизатор кешируется, если вы изменили маршрутизатор не забудьте выполнить команду для очистки кеша:
./cx cache clear
После того, как мы определились с контроллером и действием, начинается запуск контроллера, запуск происходит в несколько этапов:
- Создание объекта контроллера
- Инициализация View с которым будет работать контроллер
- Вызов метода
init() - Запуск обработчиков, которые вызываются до выполнения действия
- Вызов метода-действия
- Запуск обработчиков, которые вызываются после выполнения действия
Инициализация View заключается в указании необходимого шаблона и текущей локализации, путь к шаблону выглядит следующим образом: $controller.'/'.$action.'.xsl', для каждого контролера создается отдельный каталог, для каждого действия - отдельный файл шаблона
Отличительной особенностью запуска контроллера является наличие обработчиков до и после выполнения действий. За запуск обработчиков отвечают классы наследники CompleXml_Listener_Abstract. По умолчанию определен и вызывается CompleXml_Listener_Behaviour, в его задачи входит найти у метода действий аннотации @before и @after и выполнить у контроллера соответствующие методы
class indexController extends CompleXml_Controller{
private $_time;
//метод выполнится до indexAction()
public function beforeIndex()
{
$this->_time = microtime(true);
}
/**
* @before beforeIndex
* @after afterIndex
*/
public function indexAction()
{
//получение данных запроса
$this->Request->getString('test');
//получение данных сессии
$this->Session->getString('test');
//получение данных из куки
$this->Cookies->getString('test');
}
//метод выполнится после indexAction()
public function afterIndex()
{
$this->_time = microtime(true) - $this->_time; //время выполнения indexAction
}
}
В контроллерах доступны объекты: Request - объект, для работы с данными запроса, передается в контроллер из маршрутизатора, экземпляр класса CompleXml_Dataset_Request; Response - объект для формирования ответа, экземпляр класса CompleXml_Router_Response; Session - объект для работы с сессиями, экземпляр класса CompleXml_Dataset_Session; Cookies - объект для работы с куками, экземпляр класса CompleXml_Dataset_Cookies; View - объект для работы с отображением, экземпляр класса CompleXml_View
После выполнения контроллера, запускаются классы, отдающие ответ - классы, реализующие интерфейс CompleXml_Output_Interface. В системе определены следующие выходные классы - CompleXml_Output_Xml, CompleXml_Output_Browser, CompleXml_Output_Xslt.
Класс CompleXml_Output_Xml проверяет, что запрашиваются именно данные в XML формате и выдает их, для определения формата данных проверяется наличие заголовка X-Requested-With: XMLHttpRequest, такой заголовок устанавливают большинство javascript фреймворков при AJAX запросах, так же можно указать вручную XML формат ответа:
CompleXml_Config::setSettings('Output_Xml', array('only_xml'=>true));
CompleXml_Output_Browser проверяет есть ли возможность на стороне браузера делать xsl преобразование, проверка возможности преобразования происходит по значению User-Agent в заголовке запроса, в случае возможности преобразования, ответ отдается в виде XML с указанием шаблона для преобразования:
<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/templates/index/index.xsl"?> <page> </page>
В данный момент поддерживаются браузеры: Opera > 9.0, Firefox > 3.0, Safari > 3.0, Chrome >1.0, Safari > 3.0 и Internet Explorer > 6.0. Вы можете указать свой набор браузеров в которых будет происходить преобразование на стороне браузера:
CompleXml_Config::setSettings('Output_Browser', array(
'xslt_browsers'=>array('Opera'=>10.0, 'Chrome'=>2.0, 'IE'=>8.0)
);
);
CompleXml_Output_Xslt преобразовывает xml ответа при помощи xslt на стороне сервера и отдает браузеру результат.
Примечание: вы можете задать свои классы ответа
CompleXml_Config::setSettings('Application', array(
'outputs'=>array('CompleXml_Output_Xml', 'CompleXml_Output_Xslt') // конфигурация, позволяющая исключить браузерные преобразования xsl
)
);
При указании классов ответа, важен порядок - после успешного выполнения класса ответа, следующие не запускаются. По умолчанию порядок вызова классов ответа: CompleXml_Output_Xml, CompleXml_Output_Browser, CompleXml_Output_Xslt.
Для работы с View частью приложения используется класс CompleXml_View, он наследуется через CompleXml_View_XmlWriter от класса XMLWriter. Класс CompleXml_View доступен во всех контроллерах приложения. Для передачи данных из модели в отображение можно воспользоваться несколькими методами класса CompleXml_View:
class controllerController extends CompleXml_Controller{
public function actionAction()
{
$this->View->assign('test', 'test'); // создаст xml ветку <test>test</test>
$this->View->assign('test'); // создаст xml ветку <controller-action>test</controller-action>
$this->View->assign( // создаст xml ветку <controller-action><test>1</test></controller-action>
array('test'=>'1')
);
$this->View->writeElement('foo', 'bar'); // создаст xml ветку <foo>bar</foo>
// следующий код создаст xml ветку <foo><![CDATA[bar]]></foo>
$this->View->startElement('foo');
$this->View->writeCData('bar');
$this->View->endElement();
$array = array('foo'=>'bar', 'test'=>'test');
$this->View->writeElement('ololo', $array); // создаст xml ветку <ololo><foo>bar</foo><test>test</test></ololo>
$this->View->assign('ololo', $array); // создаст xml ветку <ololo><foo>bar</foo><test>test</test></ololo>
$this->View->assign($array); // создаст xml ветку <controller-action><foo>bar</foo><test>test</test></controller-action>
}
}
В CompleXml шаблоны для представления данных из модели пишутся на xsl, шаблоны расположены в директории firstproject/public/templates, такое расположение обусловлено необходимостью иметь доступ к шаблонам при браузерной генерации страницы. При создании проекта создаются шаблоны для отображения первой страницы, для страницы ошибок и общий layout. Пример шаблона, генерируемого при создании проекта:
<?xml version="1.0" encoding="UTF-8"?>
<!-- шаблон для index страницы, файл firstproject/public/templates/index/index.xsl -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" method="html" omit-xml-declaration="yes" indent="no"
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>
<xsl:include href="../layout.xsl" />
<xsl:template match="/">
<xsl:apply-templates select="page">
<xsl:with-param name="title">Congratulations, CompleXml project started!</xsl:with-param>
</xsl:apply-templates>
</xsl:template>readComponent
<xsl:template match="content">
<h1>Congratulations, CompleXml project started!</h1>
<p>for more informations visit <a href="http://complexml.org/docs" >documentation page</a></p>
</xsl:template>
</xsl:stylesheet>
Конфигурирование CompleXml framework построено на следующем принципе: каждый отдельный компонент может иметь свои предопределенные параметры конфигурации, они хранятся в директории ComleXmlData которая находится в директории lib фреймворка. Для получения данных о параметрах компонент воспользуйтесь CompleXml_Config:
//получение параметров CompleXml_Application
$settings = CompleXml_Config::readComponentSettings('CompleXml_Application');
//получение параметров CompleXml_Application, при получении параметров CompleXml_ можно не указывать
$settings = CompleXml_Config::readComponentSettings('Application');
//для получения конкретного параметра, можно воспользоваться
$models = CompleXml_Config::getSettings('Application', 'models');
Для переопределения параметров используйте все тот же CompleXml_Config:
//для получения конкретного параметра, можно воспользоваться
CompleXml_Config::setSettings('Application', array('models'=>'my_models'));
Для понимания того, что можно конфигурировать, рассмотрим параметры определенные в CompleXmlData, основные параметры приложения определены для CompleXml_Application:
//содержимое файла CompleXmlData/Application.php
return array(
//путь к контролерам приложения
'controllers'=> APPLICATION_HOME.
DIRECTORY_SEPARATOR.'application'.DIRECTORY_SEPARATOR.'controllers',
//путь к моделям
'models' => APPLICATION_HOME.
DIRECTORY_SEPARATOR.'application'.DIRECTORY_SEPARATOR.'models',
//путь к директории настроек приложения
'configs' => APPLICATION_HOME.
DIRECTORY_SEPARATOR.'application'.DIRECTORY_SEPARATOR.'configs',
//путь к журналам
'logs'=> APPLICATION_HOME.
DIRECTORY_SEPARATOR.'logs',
//директория, в которую указывают настройки веб сервера
'document_root'=>APPLICATION_HOME.
DIRECTORY_SEPARATOR.'public',
//путь к кешу приложения
'cache'=> APPLICATION_HOME.
DIRECTORY_SEPARATOR.'cache',
//драйвер для кеша
'cache_driver'=> new CompleXml_Cache_Driver_File(array('dirname'=>APPLICATION_HOME.
DIRECTORY_SEPARATOR.'cache')),
//локаль по умолчанию
'default_locale'=>'en_EN',
//режим отладки
'debug_mode'=>false,
// кеширование маршрутизаторов
'router_cache'=> true,
//шаблон для имени контроллеров
'controller_template'=> '%sController',
//шаблон для имени метода-действия
'action_template'=> '%sAction',
//маршрутизатор по умолчанию
'default_router'=> 'CompleXml_Router_Default',
//метод-действие по умолчанию
'default_action'=> 'index',
//контроллер по умолчанию
'default_controller'=> 'index',
//слушатели событий
'listeners' => array('CompleXml_Listener_Behaviour'),
//классы ответа приложения
'outputs' => array('CompleXml_Output_Xml', 'CompleXml_Output_Browser', 'CompleXml_Output_Xslt')
);
Параметры для CompleXml_View:
//содержимое файла CompleXmlData/View.php
return array(
// главная ветка генерируемого xml документа
'root'=>'page',
// ветка xml, содержащая данные добавляемые из контролеров
'content_node'=>'content'
);
Параметры для CompleXml_Cli:
//содержимое файла CompleXmlData/Cli.php
//задачи, выполняемые в режиме командной строки
$tasks = array('CompleXml_Cli_Task_Help','CompleXml_Cli_Task_Cache','CompleXml_Cli_Task_Create');
if (class_exists('Doctrine')||class_exists('Doctrine_Manager')){
//если подключена Doctrine, добавляется задача для работы с ORM Doctrine из командной строки
$tasks[] = 'CompleXml_Cli_Task_Doctrine';
}
return array(
//описание правил для анализа параметров командной строки
'options' => array(
'--task'=>array(
'type'=>'String',
'position'=>1
),
'--action'=>array(
'type'=>'String',
'position'=>2
)
),
//слушатели событий
'listeners' => array('CompleXml_Listener_Behaviour'),
'tasks'=>$tasks
);
Параметры для CompleXml_Output_Browser:
//содержимое файла CompleXmlData/Output/Browser.php
return array(
// сохраняет данные о браузере посетителя в сессию
'with_get_browsers_cache'=> false,
// список браузеров, поддерживающих xslt преобразования
'xslt_browsers'=>
array('Opera'=>9.0, 'Firefox'=>3.0, 'Safari'=>3.0, 'Chrome'=>1.0, 'IE'=>6.0, 'Safari'=>3.0),
//путь к шаблонам
'templates'=> '/templates',
//путь к файлам локализации
'locales'=> '/locales',
);
Параметры для CompleXml_Output_Xml:
//содержимое файла CompleXmlData/Output/Xml.php
//указывает на то, что данные нужны только в формате xml
return array('only_xml'=>false);
Параметры для CompleXml_Output_Xslt
//содержимое файла CompleXmlData/Output/Xslt.php
$CONFIG = array();
//путь к шаблонам, если шаблоны не доступны в директории проекта, то они берутся из document_root директории
if (file_exists(APPLICATION_HOME.DIRECTORY_SEPARATOR.'application'.DIRECTORY_SEPARATOR.'templates')){
$CONFIG['templates'] = APPLICATION_HOME.DIRECTORY_SEPARATOR.'application'.DIRECTORY_SEPARATOR.'templates';
}else{
$CONFIG['templates'] = CompleXml_Config::getSettings('Application', 'document_root').DIRECTORY_SEPARATOR.'templates';
}
//путь к файлам локализации, если файлы не доступны в директории проекта, то они берутся из document_root директории
if (file_exists(APPLICATION_HOME.DIRECTORY_SEPARATOR.'application'.DIRECTORY_SEPARATOR.'locales')){
$CONFIG['locales'] = APPLICATION_HOME.DIRECTORY_SEPARATOR.'application'.DIRECTORY_SEPARATOR.'locales';
}else{
$CONFIG['locales'] = CompleXml_Config::getSettings('Application', 'document_root').DIRECTORY_SEPARATOR.'locales';
}
return $CONFIG;
CompleXml не навязывает конкретные инструменты для работы с базами данных. В CompleXml framework входит несколько классов для работы с БД: CompleXml_Db_Connection, CompleXml_Db_Doctrine.
CompleXml_Db_Connection наследник класса PDO, умеет логировать запросы при помощи CompleXml_Log, при сбоях возвращает исключение CompleXml_Db_Exception, может использоваться в разных ORM как соединение с базой данных.
//создание соединения
$connection = new CompleXml_Db_Connection('sqlite::memory:');
//выполнение запроса, $res - число затронутых полей
$res = $connection->exec('CREATE TABLE t(x INTEGER PRIMARY KEY DESC, y, z);'); // $res = 0
$res = $connection->exec('INSERT INTO t (x, y, z) VALUES (1, "111", 123);'); // $res = 1
//получение списка ответов
$resultArray = $connection->query('SELECT * FROM t')->fetchAll();
CompleXml framework легко интегрируется с ORM Doctrine, для подключения Doctrine в firstproject/configs/main.ini.php нужно добавить следующий код:
require_once('Doctrine.php');
spl_autoload_register(array('Doctrine', 'autoload'));
$doctrine_config = array(
'data_fixtures_path' => '/path/to/data_fixtures',
'models_path' => CompleXml_Config::getSettings('Application', 'models'), //путь к моделям
'migrations_path' => '/path/to/migrations',
'sql_path' => '/path/to/sql',
'yaml_schema_path' => '/path/to/database_schema.yml',
'connection' => 'connections params or PDO object' //параметры соединения
);
Doctrine_Manager::getInstance()->setAttribute('autoload_table_classes', true);
Doctrine_Manager::getInstance()->setAttribute('model_loading', 'conservative');
Doctrine::loadModels($doctrine_config['models_path']);
Doctrine_Manager::connection($doctrine_config['connection']);
CompleXml_Config::set('doctrine_config', $doctrine_config);
Дополнительная информация о ORM Doctrine доступна по адресу http://www.doctrine-project.org/documentation.
CompleXml_Db_Doctrine - вспомогательный класс для работы с ORM Doctrine. Позволяет получать доступ к Doctrine_Pager как к массиву:
$currentPage = 1;
$resultsPerPage = 50;
$pager = new Doctrine_Pager(
Doctrine_Query::create()
->from( 'User u' )
->leftJoin( 'u.Group g' )
->orderby( 'u.username ASC' ),
$currentPage,
$resultsPerPage
);
$result = $pager->execute();
$pagerArray = CompleXml_Db_Doctrine($pager);
//$pagerArray - массив данных о Doctrine_Pager, такой вид выгоднее отличается от простого объекта при создании xml.
CompleXml framework предоставляет простые и гибкие средства для кеширования. Идея кеширования в CompleXml состоит из таких понятий:
- Драйверы кеширования - классы для работы с разными хранилищами данных, реализуют интерфейс
CompleXml_Cache_Driver_Interface, доступны драйверы для Memcache, Apc, Xcache и File кеш. - Критерии кеширования - критерии по которым определяется актуальность данных в кеше, реализуют интерфейс
CompleXml_Cache_Criteria_Interface, доступны критерииCompleXml_Cache_Criteria_LifetimeиCompleXml_Cache_Criteria_Tag - Менеджер кеша
CompleXml_Cache
Пример работы с кешем:
//создание драйвера кеша
$cache_driver = new CompleXml_Cache_Driver_Xcache();
$cache = new CompleXml_Cache($cache_driver);
// установка кеша с временем жизни 50 секунд и двумя тегами 'tagA', 'tagB'
$cache->set('test', 'test', 50, array('tagA', 'tagB'));
$val = $cache->get('test'); // $val == 'test';
// создание объекта критерия кеша
$cacheTagA = new CompleXml_Cache_Criteria_Tag($cache_driver, array('name'=>'tagA'));
// сброс кеша по критерию
$cacheTagA->flush();
$val = $cache->get('test'); // $val === false
// установка кеша с произвольными критериями
// установка кеша с временем жизни 100 секунд и двумя тегами 'tagX', 'tagZ'
$cache->set('test', 'test', false, false,
array(
new CompleXml_Cache_Criteria_Lifetime($cache_driver, array('time'=>100)),
new CompleXml_Cache_Criteria_Tag($cache_driver, array('name'=>'tagX')),
new CompleXml_Cache_Criteria_Tag($cache_driver, array('name'=>'tagZ')),
)
);
Для работы с массивами данных в CompleXml framework введен класс CompleXml_Dataset
Для работы множествами данных родительский класс CompleXml_Dataset содержит следующие методы:
-
getValue($name, $default = null, CompleXml_Validate_Abstract $validator = null)- метод возвращает данные из множества, в случае отсутствия данных отдает $default значение, $validator содержит класс, проверяющий данные перед отдачей, если данные не прошли проверку, отдается $default значение. -
getString ($name, $default = null, $min_length = null, $max_length = null)— возвращает строку из множества, если длина строки не в пределах $minlength<=длина строки<= $maxlength, то возвращается $default значение. -
getEmail ($name, $default = null)— возвращает данные из множества, если данные проходят проверку на e-mail. -
getDomainName ($name, $default = null)возвращает данные из множества, если данные проходят проверку на доменное имя. -
getInt ($name, $default = null, $min = null, $max = null)— возвращает целое число, если оно есть в множестве и находится в пределах от $min до $max -
getBool ($name, $default = false)— возвращает булево значение данных из множества. -
getAllValues ()- возвращает массив всех значений -
setValue($name, $value)— устанавливает значение в множество. -
setValues($values)— устанавливает все значения.
Класс CompleXml_Dataset реализует интерфейсы Countable и Iterator,что позволяет работать с ним как с массивом.
CompleXml_Dataset_Request содержит данные о запросе, массив $_REQUEST и данные найденные в аннотациях маршрутизатора. У класса есть 3 публичных элемента - CompleXml_Dataset_Request->Post — объект CompleXml_Dataset содержащий $_POST, CompleXml_Dataset_Request->Get — объект CompleXml_Dataset содержащий $_GET, CompleXml_Dataset_Request->Uri — данные из строки запроса, разбитые по «/».
CompleXml_Dataset_Session содержит множество данных $_SESSION, в классе переопределен метод setValue(),
при вызове этого метода, данные устанавливаются в сессию пользователя. Добавлены методы destroy() - уничтожает сессию и unregister($name) — удаляет переменную из сессии.
CompleXml_Dataset_Cookies содержит множество данных $_COOKIES, в классе переопределен метод setValue(),
при вызове этого метода, данные устанавливаются в cookies пользователя.
Для решения задач связаных с авторизацией и правами доступа в CompleXml предусмотренны модули CompleXml_Auth и CompleXml_Acl.
В модуль авторизации входит несколько классов: CompleXml_Auth - класс singleton который управляет авторизацией пользователя, CompleXml_Auth_Result - класс, хранящий информацию о авторизации и о авторизированом пользователе, CompleXml_Auth_Listener - класс наследник CompleXml_Listener_Abstarct, предназначен для определения доступности мотодов контролера авторизованым и неавторизованым пользователям.
Примеры работы с CompleXml_Auth:
//информация о пользователе, может быть любым типом данных
$user = array('id'=>1, 'name'=>'user');
//Авторизация пользователя
CompleXml_Auth::getInstance()->authenticate($user);
//проверка авторизации пользователя
if (CompleXml_Auth::getInstance()->isAuth()){
//пользователь авторизирован
}else{
//пользователь не авторизирован
}
//дата авторизации
$date = CompleXml_Auth::getInstance()->getDate();
//очистка информации о авторизированом пользователе
CompleXml_Auth::getInstance()->clearIdentity();
//установка информации о неудачной авторизации
CompleXml_Auth::getInstance()->brokenAuth();
//Установка ролей пользователя, роли необходимы для работы с правами доступа
CompleXml_Auth::getInstance()->addRole('admin');
CompleXml_Auth::getInstance()->addRole('editor');
CompleXml_Auth::getInstance()->setRoles(array('user1', 'user2'));
//Получение ролей пользователя
$roles = CompleXml_Auth::getInstance()->getRoles();
// Метод возвращает список ролей только в том случае, если пользователь авторизирован
// Очищает информацию о роляж пользователя
CompleXml_Auth::getInstance()->flushRoles();
Для работы с правами доступа в CompleXml используется модуль CompleXml_Acl, он состоит из следующих классов: CompleXml_Acl - класс для управления правами доступа, CompleXml_Acl_Role - класс, описывающий роль пользователя, CompleXml_Acl_Resource - класс, описывающий ресурс к которому будет проверяться доступ, CompleXml_Acl_Listener - наследник класса CompleXml_Listener_Abstract, предназначен для определения доступа к методам контролера в зависимости от ролей текущего пользователя.
Примеры использования CompleXml_Acl:
//Создание менеджера для управления правами доступа
$acl = new CompleXml_Acl();
//Создание роли
$role = new CompleXml_Acl_Role('role');
//Создание ресурса
$resource = new CompleXml_Acl_Resource('resource');
//Добавление роли к менеджеру acl
$acl->addRole($role);
//Добавление ресурса к менеджеру acl
$acl->addResource($resource);
//установка запрета для доступа к ресурсу resource для роли role
$acl->deny('resource', 'role');
if ($acl->isDeny('resource', 'role')){
//проверка запрета для доступа к ресурсу
}
//установка разрешения доступа к ресурсу resource для роли role
$acl->allow('resource', 'role');
if ($acl->isAllow('resource', 'role')){
//проверка разрешения доступа к ресурсу
}
Пример контролера с использованием CompleXml_Auth и CompleXml_Acl:
class exampleController extends CompleXml_Controller
{
/**
* Метод доступен для всех пользователей
*/
public function loginAction()
{
$name = $this->Request->Post->getString('name');
$password = $this->Request->Post->getString('password');
if (($name=='name')&&($password=='password')){
CompleXml_Auth::getInstance()->authenticate(array('name'=>$name));
CompleXml_Auth::getInstance()->addRole('user');
}
if (($name=='admin')&&($password=='adminpassword')){
CompleXml_Auth::getInstance()->authenticate(array('name'=>$name));
CompleXml_Auth::getInstance()->addRole('admin');
}
}
/**
* Метод secretAction доступен только для авторизированных пользователей
* @auth true
*/
public function secretAction()
{
}
/**
* Метод adminAction доступен только для авторизированных пользователей
* с ролью admin
* @allow admin
*/
public function adminAction()
{
}
/**
* Метод danyUserAction доступен только для авторизированных пользователей
* с ролью оличной от user
* @deny user
*/
public function denyUserAction()
{
}
}
Примечание: для работы с анотациями @auth, @allow и @dany необходимы подключенные классы CompleXml_Auth_Listener и CompleXml_Acl_Listener, которые по умолчанию не подключены, для подключения необходимо выполнить код:
CompleXml_Config::setSettings('Application',
array('listeners' => array('CompleXml_Auth_Listener', 'CompleXml_Acl_Listener'))
);
Для ведения журналов в системе предназначен модуль CompleXml_Log, его особенностью является то, что процесс журналирования происходит через статические методы, что позволяет уменьшить используемую память и ускорить ведения журналов.
Ведение журналов можно разделить на три этапа: запись, форматирование и фильтрация журналов.
За запись журналов отвечают классы-наследники CompleXml_Log_Writer_Abstract, за форматирование - CompleXml_Log_Format_Abstract и за фильтрацию данных для журналов ComleXml_Log_Filter_Abstract.
Методы модуля:
- CompleXml::add ($message, $type) — добавление записи в журнал
- CompleXml::addWriter (CompleXml_Log_Writer_Abstract $writer) — добавление потока сохранения журнала.
Типы сообщений журналирования в порядке убывания приоритета:
const EMERG = 0; const ALERT = 1; const CRIT = 2; const ERR = 3; const WARN = 4; const NOTICE = 5; const INFO = 6; const DEBUG = 7;
Пример использования CompleXml_Log
// создание класса, записывающего журнал
$writer = new CompleXml_Log_Writer_Stream('/var/logs/complexml.log');
// установка формата записей в журнале
$writer->setFormat(new CompleXml_Log_Format_Simple());
// установка фильтра журнала по типу сообщения
$types = array(CompleXml_Log::ERR, CompleXml_Log::DEBUG);
$writer->addFilter(new CompleXml_Log_Filter_Type($types));
CompleXml_Log::addWriter($writer);
CompleXml_Log::add('Debug message', CompleXml_Log::DEBUG); // сообщение будет записано в журнал
CompleXml_Log::add('Info message', CompleXml_Log::INFO); // сообщение не будет записано в журнал
Одним из преимуществ CompleXml framework является его высокая производительность, в качестве доказательств здесь приведены сравнительный тесты производительности с такими известными фреймворками как Zend Framework 1.9.3PL1, symfony 1.2.9 и позиционирующем себя как самый быстрый фреймворк Yii 1.0.10.r1472.
Как проводились тесты, на сайтах фреймворков были получены их свежие версии, в документациях по руководствам быстрый старт, развернуты типичные проекты, в настройках apache созданы виртуальные хосты под каждый проект, далее на каждый виртуальный хост выполнялась команда:
ab -t 30 -c 10 {имя хоста}
После выполнения команды, веб сервер перегружался. Количество вызовов функций измерялось при помощи Xdebug's Profiler.
Оборудование и программное обеспечение:
Processor: AMD Turion(tm) 64 Mobile Technology ML-37(2GHz)
Memory: 2060MB
Operating System: Ubuntu 9.10
Server version: Apache/2.2.12 (Ubuntu)
PHP 5.2.10-2ubuntu6.1 with Suhosin-Patch 0.9.7 (cli) (built: Oct 29 2009 19:28:39)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies
with XCache v1.2.2, Copyright (c) 2005-2007, by mOo
with Xdebug v2.0.4, Copyright (c) 2002-2008, by Derick Rethans
Сводная таблица:
| | Всего запросов | Запросов в секунду | Передано данных(байт) | Вызовов функций |
|---|---|---|---|---|
| CompleXml 0.3.1 | 509 | 16,97 | 545648 | 168 |
| CompleXml 0.3.1 (только XML ответ) | 856 | 28,52 | 466520 | 128 |
| Zend Framework 1.9.3PL1 | 222 | 7,39 | 278832 | 406 |
| Symfony 1.2.9 | 149 | 4,91 | 347700 | 495 |
| Yii 1.0.10.r1472 | 424 | 14,11 | 1503080 | 271 |