Три с половиной месяца прошло со дня релиза MODx Revolution. Думаю никто не будет спорить, что версия 2.0 была очень сырой и для использования на реальных проектах была не готова. На русскоязычных сайтах о MODx я видел много критики и скептицизма. Что-то вполне заслужено, а что-то из-за отсутствия подробной документации. На данный момент доступна версия 2.0.4-pl2, по которой, на мой взгляд, уже можно подвести итоги: Правильно ли разработчики выбрали направление и инструменты для развития и стоит ли отказаться от MODx Evolution (1.x) и переходить на Revo? В данной статье я постараюсь подробно рассказать об основных особенностях новой системы, которые сам для себя только открываю.
Как говорят разработчики, в первую очередь MODx Revolution — это CMF, т.е. инструмент для создания веб-приложений, а CMS, которая идет в комплекте, это всего лишь «довесок». Рево написан на PHP и использует:
Несмотря на вышесказанное, разработчики уделили не мало внимания CMS. Чувствуется, что удобство системы управления продумано очень тщательно.
Если нажать правой кнопкой мыши на каком-то разделе в дереве ресурсов (документов) слева и выбрать «Быстро создать» -> «Документ», то откроется окно для создания документа без перезагрузки страницы, что очень удобно. Есть и быстрое редактирование («Быстро обновить ресурс»). Точно так же можно быстро создать или отредактировать «дополнительные поля» и т.п. Документы можно сортировать и перекладывать по разделам простым перетаскиванием в дереве.
Впрочем, не всё так радужно. Из-за кучи «JavaScript-красивостей» админка работает заметно медленнее чем в Evolution, иногда подвисает на каких-то действиях. Хотя думаю со временем это всё поправится (критичных глюков я не заметил).
Разделение прав пользователей. В Evo права были фиксированные и только в админке (для «менеджеров»). В Revo появилась возможность создавать свои права и назначать их отдельным группам пользователей. Делается это очень просто:
Идем в «Безопасность» -> «Группы пользователей» -> «Политики доступа». Выбираем имя политики доступа (например «Administrator») и в редактировании добавляем «новое разрешение», например «test_action».
Сохраняем и жмем «Выйти». Чтобы права обновились, нужно заново войти в систему (обновить сессию). Теперь можно в любом месте в коде компонента (сниппета, плагина) проверить имеет ли текущий пользователь права на действие «test_action»:
Это очень коротко, есть возможность настроить права доступа более тонко. В Revo нет разделения на «менеджеров» и «веб-пользователей» как в Evo. Контроль доступа в административной части определяется контекстом «mgr», а во внешней части сайта — контекстом «web».
Создание сниппетов и плагинов без особенных изменений. Сохранены большинство названий функций и аргументы из Evo. Для создания «пакетов» (packages) есть очень удобный и простой в работе модуль PackMan:
Выбираем сниппеты, плагины, чанки, нажимаем кнопку «Export Transport Package» и получаем готовый к установке архив пакета. Теперь можно будет его положить в папку core/packages/ и установить через «Управление пакетами».
Создание страниц в «менеджере». Теперь нет понятия «Модуль». Есть общее название «Компонент». В системе управления можно создать пользовательский интерфейс администрирования компонента. Опишу коротко основные шаги:
1. Создаем пространство имен для нашего компонента («Система» -> «Пространства имен»).
По указанному пути «менеджер» будет искать «контроллер» компонента. Если вы знакомы с паттерном MVC, то понятие «контроллер» вам хорошо известно.
2. Идем в «Система» -> «Действия». Кликнув на нашем пространстве имен «myextra», выбираем «Создать действие здесь». В строке «Контроллер» пишем название PHP-файла контроллера, который лежит в папке указанной ранее. Например «index» (index.php).
3. Теперь создаем пункт в главном меню. Кликаем правой кнопкой мыши на пункте «Компоненты» в блоке «Верхнее меню» и выбираем «Создать пункт меню здесь».
4. В более сложных приложениях стоит все контроллеры складывать в отдельную папку «controllers». Вот содержание моего контроллера index.php:
В реальности так делать очень не рекомендуется. Нужно создать модель и т.п. (об этом в следующей части). Можно использовать шаблонизатор Smarty:
Можно использовать PHP в роли шаблонизатора (шаблоны нужно вынести в отдельный файл). А можно по-полной использовать ExtJS. Вот пример вывода таблицы значений (Ext.grid.GridPanel):
core/components/myextra/index.php:
assets/components/myextra/js/datagrid.js:
assets/components/myextra/connector.php:
core/components/myextra/processors/mgr/datalist.php:
В итоге получаем такую табличку:
ExtJS совсем не сложен в изучении, как мне раньше казалось. Главное желание. Он действительно экономит кучу времени.
Документация MODx Revolution покаочень бедная. Немалую часть информации приходится искать в исходниках. Надеюсь скоро эта ситуация изменится, возможно, с вашей помошью.
Конец первой части.
Из этой части думаю всем понятно, что MODx Revolution не на много сложнее Evolution в плане разработки, а возможностей для разработчика на порядок больше.
Что такое MODx Revolution
Как говорят разработчики, в первую очередь MODx Revolution — это CMF, т.е. инструмент для создания веб-приложений, а CMS, которая идет в комплекте, это всего лишь «довесок». Рево написан на PHP и использует:
- базу данных MySQL,
- технологию преобразования объектов в реляционные модели баз данных xPDO,
- JavaScript фреймворк Sencha (ExtJS),
- шаблонизатор Smarty.
Система управления
Несмотря на вышесказанное, разработчики уделили не мало внимания CMS. Чувствуется, что удобство системы управления продумано очень тщательно.
- Выпадающее меню с кратким описанием каждого пункта (кому не нравится, описания можно отключить);
- вкладки на панеле слева с быстрым доступом ко всем основным элементам и файлам;
- почти всё (а может и совсем всё) можно настроить под конкретный проект без необходимости залезать в исходный код;
- встроенный поиск ресурсов (документов);
- удобная установка пакетов (дополнений) прямо из CMS.
Если нажать правой кнопкой мыши на каком-то разделе в дереве ресурсов (документов) слева и выбрать «Быстро создать» -> «Документ», то откроется окно для создания документа без перезагрузки страницы, что очень удобно. Есть и быстрое редактирование («Быстро обновить ресурс»). Точно так же можно быстро создать или отредактировать «дополнительные поля» и т.п. Документы можно сортировать и перекладывать по разделам простым перетаскиванием в дереве.
Впрочем, не всё так радужно. Из-за кучи «JavaScript-красивостей» админка работает заметно медленнее чем в Evolution, иногда подвисает на каких-то действиях. Хотя думаю со временем это всё поправится (критичных глюков я не заметил).
Разработка под MODx Revolution
Разделение прав пользователей. В Evo права были фиксированные и только в админке (для «менеджеров»). В Revo появилась возможность создавать свои права и назначать их отдельным группам пользователей. Делается это очень просто:
Идем в «Безопасность» -> «Группы пользователей» -> «Политики доступа». Выбираем имя политики доступа (например «Administrator») и в редактировании добавляем «новое разрешение», например «test_action».
Сохраняем и жмем «Выйти». Чтобы права обновились, нужно заново войти в систему (обновить сессию). Теперь можно в любом месте в коде компонента (сниппета, плагина) проверить имеет ли текущий пользователь права на действие «test_action»:
if (!$modx->hasPermission('test_action')){
//Если прав на это действие нет, выводим сообщение "Доступ закрыт"
return $modx->error->failure($modx->lexicon('access_denied'));
}
Это очень коротко, есть возможность настроить права доступа более тонко. В Revo нет разделения на «менеджеров» и «веб-пользователей» как в Evo. Контроль доступа в административной части определяется контекстом «mgr», а во внешней части сайта — контекстом «web».
Создание сниппетов и плагинов без особенных изменений. Сохранены большинство названий функций и аргументы из Evo. Для создания «пакетов» (packages) есть очень удобный и простой в работе модуль PackMan:
Выбираем сниппеты, плагины, чанки, нажимаем кнопку «Export Transport Package» и получаем готовый к установке архив пакета. Теперь можно будет его положить в папку core/packages/ и установить через «Управление пакетами».
Создание страниц в «менеджере». Теперь нет понятия «Модуль». Есть общее название «Компонент». В системе управления можно создать пользовательский интерфейс администрирования компонента. Опишу коротко основные шаги:
1. Создаем пространство имен для нашего компонента («Система» -> «Пространства имен»).
По указанному пути «менеджер» будет искать «контроллер» компонента. Если вы знакомы с паттерном MVC, то понятие «контроллер» вам хорошо известно.
2. Идем в «Система» -> «Действия». Кликнув на нашем пространстве имен «myextra», выбираем «Создать действие здесь». В строке «Контроллер» пишем название PHP-файла контроллера, который лежит в папке указанной ранее. Например «index» (index.php).
3. Теперь создаем пункт в главном меню. Кликаем правой кнопкой мыши на пункте «Компоненты» в блоке «Верхнее меню» и выбираем «Создать пункт меню здесь».
4. В более сложных приложениях стоит все контроллеры складывать в отдельную папку «controllers». Вот содержание моего контроллера index.php:
<?php
$corePath = MODX_CORE_PATH.'components/myextra/';
$assetsUrl = MODX_BASE_URL.'assets/components/myextra/';
$controllersPath = $corePath.'controllers/';
$connectorUrl = $assetsUrl.'connector.php';
$cssUrl = $assetsUrl.'css/';
$jsUrl = $assetsUrl.'js/';
$output .= '<div><h2>Тестовый компонент</h2></div>';
$output .= '<div id="myextra-main-div"></div>';
return $output;
В реальности так делать очень не рекомендуется. Нужно создать модель и т.п. (об этом в следующей части). Можно использовать шаблонизатор Smarty:
$title = 'Тестовый компонент';
//передаем переменную в шаблон
$modx->smarty->assign('title', $title);
//выводим шаблон
return $modx->smarty->fetch($corePath.'templates/main.tpl');
Можно использовать PHP в роли шаблонизатора (шаблоны нужно вынести в отдельный файл). А можно по-полной использовать ExtJS. Вот пример вывода таблицы значений (Ext.grid.GridPanel):
core/components/myextra/index.php:
<?php
$corePath = MODX_CORE_PATH.'components/myextra/';
$assetsUrl = MODX_BASE_URL.'assets/components/myextra/';
$controllersPath = $corePath.'controllers/';
$connectorUrl = $assetsUrl.'connector.php';
$cssUrl = $assetsUrl.'css/';
$jsUrl = $assetsUrl.'js/';
//подключаем скрипты в HEAD
$modx->regClientStartupHTMLBlock('<script type="text/javascript">
var myextra = {};
myextra.connector_url = "'.$connectorUrl.'";
</script>');
$modx->regClientStartupScript($jsUrl.'datagrid.js'); //скрипт с grid`ом
$output .= '<h2>Тестовый компонент</h2>';
$output .= '<div id="myextra-main-div"></div>';
return $output;
assets/components/myextra/js/datagrid.js:
Ext.onReady(function(){
//создаем хранилище данных
var store = new Ext.data.JsonStore({
url: myextra.connector_url, //файл источника данных
root: 'object.data', //JSON объект с основными данными
totalProperty: 'object.total', //число элементов в списке
idProperty: 'orderid',
remoteSort: false,
prettyUrls: false,
fields: [
{name: 0},
{name: 1, type: 'int'},
{name: 2, type: 'float'},
{name: 3, type: 'int'}
]
});
store.setDefaultSort(3, 'desc');
//создаем таблицу данных
var grid = new Ext.grid.GridPanel({
store: store,
columns: [
{header: "Колонка 1", width: 100, sortable: true, dataIndex: 0},
{header: "Колонка 2", width: 100, sortable: true, dataIndex: 1},
{header: "Колонка 3", width: 100, sortable: true, dataIndex: 2},
{header: "Колонка 4", width: 100, sortable: true, dataIndex: 3}
],
renderTo:'myextra-main-div', //DIV в который вставляем таблицу
width:400,
autoHeight: true,
loadMask: true,
bbar: new Ext.PagingToolbar({
pageSize: 5, //элементов на странице
store: store, //источник данных
displayInfo: true,
displayMsg: 'Показано {0} - {1} из {2}',
emptyMsg: "Ничего не найдено"
})
});
//загружаем данные
store.load({params:{
action: 'mgr/datalist', //действие ("процессор")
start:0,
limit:5
}
});
});
assets/components/myextra/connector.php:
<?php
/**
* Myextra Connector
*
* @package myextra
*/
require_once dirname(dirname(dirname(dirname(__FILE__)))).'/config.core.php';
require_once MODX_CORE_PATH.'config/'.MODX_CONFIG_KEY.'.inc.php';
require_once MODX_CONNECTORS_PATH.'index.php';
/* handle request */
$modx->request->handleRequest(array(
'processors_path' => $modx->getOption( 'core_path' ) . 'components/myextra/processors/',
'location' => ''
));
core/components/myextra/processors/mgr/datalist.php:
<?php
$start = $scriptProperties['start']; //получаем данные запроса
$limit = $scriptProperties['limit']; //получаем данные запроса
$total = 50;
$page = $start+1;
//вместо этой "рыбы" будет mysql-запрос
$limit_on_page = $total-($total-($page*$limit));
$outputArray = array();
for($i=$start*$limit;$i<$limit_on_page;$i++){
$outputArray[] = array('Строка '.($i+1),2,3,4);
}
$outputArray = array(
'total'=>$total,
'limit_on_page'=>$limit_on_page,
'data'=>$outputArray
);
return $modx->error->success('',$outputArray);
В итоге получаем такую табличку:
ExtJS совсем не сложен в изучении, как мне раньше казалось. Главное желание. Он действительно экономит кучу времени.
Документация MODx Revolution пока
Конец первой части.
Из этой части думаю всем понятно, что MODx Revolution не на много сложнее Evolution в плане разработки, а возможностей для разработчика на порядок больше.