Почему ещё одна CMS?
На самом деле скорее CMF, а название сложилось исторически. Смысл CMS/CMF в том, чтобы сделать разработку сайта проще, быстрее и дешевле. Но в реальной жизни можно столкнуться с тем, что отклонение от стандартного поведения в CMS вынуждает лезть в исходники ядра, что чревато последующими проблемами с обновлением и безопасностью, а в CMF можно столкнуться с высоким порогом входа и достаточно большим весом системы.
Моей целью было сделать баланс функциональности, сложности и удобства как можно более гармоничным.
Система имеет определённое количество велосипедов, немного магии, и большие планы.
На данный момент CleverStyle CMS может быть интересной игрушкой именно для разработчиков, так как позволяет быстро начать разработку и получать результаты, предоставляет сложным и/или рутинным задачам простой интерфейс, потому и статья об некоторых технических особенностях с примерами в общем.
Системные требования
- Unix-подобная ОС
- Apache2 (Nginx не тестировался, но точно будет поддерживаться в будущем)
- PHP 5.4+
- MySQL
Поддержка Windows отпала постепенно, слишком много оберток нужно было поддерживать для того, чтобы заставить всё работать идентично, и в определённый момент было решено выбросить это всё во имя простоты и скорости.
Возможно, и будет работать, но гарантий никаких не даю.
С чего начать
Начинается всё с установки. Она предельно простая: один установочный файл (автономный), одна страничка, несколько полей. Так, как чаще всего используется БД MySQL, а хост localhost — они используются по-умолчанию, но в режиме эксперта это можно изменить.
Установочный файл являет собой phar архив, и содержит в себе как установщик, так и исходники всей системы, а так же может комплектоваться произвольным набором компонентов. Для создания такого установщика есть специальный сборщик, который позволяет делать произвольные сборки в графическом режиме.
Что дальше
Результатом первого шага является готовая пустая CMS c гостем и корневым администратором (что-то вроде root в Linux).
Если вы — разработчик, вам захочется что-то написать. Начать можно с простого файла index.html c содержимым:
Привет, мой друг!
Затем зайти в components/modules от корня сайта, создать директорию Hello и бросить туда index.html
Это готовый модуль, чтобы его активировать нужно зайти в админку Компоненты/Модули, нажать Обновить список модулей. Появившийся модуль нужно установить и включить, после чего он появится в меню:
Вот так просто.
Немного более сложный вариант — использовать вместо index.html файл index.php.
В этом случае простым выводом уже не обойтись:
global $Page;
$Page->content('Привет, мой друг!');
Впрочем, не на много сложнее. Таких как $Page глобальных системных объектов несколько:
$Cache, $Config, $Core, $db, $Error, $Index, $Key, $L, $Mail, $Page, $Storage, $Text, $User
Все они доступны практически всегда, и отвечают каждый за свою часть общей функциональности. В общем название объекта соответствует названию класса (с некоторыми исключениями).
Все методы и некоторые (пока не все) свойства объектов имеют PhpDoc секции с объяснением типов входящих параметров, их описанием и даже некоторыми примерами входных данных. В wiki все объекты описаны, и многие имеют примеры готового кода, который можно скопировать 1 в 1 и он будет работать.
Так же есть один системный класс h, который используется как статический для рендеринга HTML с помощью CSS-подобного синтаксиса:
global $Page;
$Page->content(h::p('Параграф');
$Page->content(h::{'h1#some_id.and-class.another-class[data-type=title]'}('Заголовок статьи');
Простота и удобство разработчика
Система поддерживает работу с несколькими БД и их зеркалами одновременно, поддерживает различные backend-ы для кеша, умеет работать с несколькими хранилищами статических файлов и прочими вещами, но предоставляет для разработчика простой интерфейс взаимодействия со всем этим.
Работа с объектами сделана максимально натуральной и очевидной (вот тут немного магии):
global $Cache;
$Cache->item = 5;
$item = $Cache->item;
unset($Cache->item); //Хотя можно использовать и ::get() ::set() ::del() методы если вы правда считаете что эта магия будет для вас узким местом
$Cache->{'Movies/1'} = 1;
$Cache->{'Movies/2'} = 2;
unset($Cache->Movies); //Удаляет оба фильма из кеша
С многоязычным интерфейсом работать тоже легко:
global $L, $Page;
$Page->content($L->hello); //Здравствуйте
Так же можно использовать следующую интересную конструкцию:
global $L, $Page;
$Page->content($L->installation_of_module('Hello')); //Установка модуля Hello
Файлы перевода — JSON, а строки могут быть оформлены как для функции sprintf. Для предыдущего примера:
"installation_of_module" : "Установка модуля %s"
Так можно делать персонализированные сообщения.
Аналогичный формат используется при работе с БД:
global $db;
$db->q(
"SELECT `login`
FROM `[prefix]users`
WHERE `id` = '%d'",
2
);
В этом примере перед подстановкой значение ещё будет обработано для защиты от SQL инъекций.
В случае нескольких запросов за раз можно так:
global $db;
$db->q(
[
"DELETE FROM `[prefix]users`
WHERE `id` = '%d'",
"DELETE FROM `[prefix]users_groups`
WHERE `id` = '%d'"
],
2
);
Кроме очевидности написанного, такой код красиво подсвечивает IDE.
Структура сайта
Сайт имеет обычные страницы для конечного польззователя, как было в первых примерах, административные, и странички API, которые не имеют интерфейса и отдают контент в формате JSON.
Простой пример как создать API для нашего модуля Hello.
Создаем внутри components/modules/Hello директорию api, а в ней файл index.php c содержимым:
global $Page;
$Page->json([
'title' => 'Привет!',
'description' => 'Приветствие хабрахабру через API'
]);
И обратившись с помощью jQuery по адресу api/Hello нам придет JSON строка с необходимым заголовком и телом.
Что система вообще умеет:
- Поддержка компонентов
- Поддержка модулей (для отображения основного содержания страницы)
- Поддержка плагинов (загружаются на каждой странице и обеспеивают дополнительную функциональность)
- Поддержка блоков (размещаются вокруг страницы для отображения дополнительной информации)
- Поддержка человекочитаемых адресов
- Поддержка типов и групп пользователей
- Поддержка прав и контроля доступа
- Полная многоязычная поддержка (как интерфейса, так и контента)
- Поддержка автоматического перевода контента
- Поддержка минификации и компрессии CSS и JavaScript
- Поддержка зекрал сайта
- Поддержка зеркал доменов
- Поддержка зеркал физических серверов для каждого домена
- Поддержка тем и цветовых схем
- Поддержка множественных баз данных
- Поддержка множественных зеркал баз данных
- Поддержка множественных хранилищ файлов
- Поддержка системного кэширования
- Фильтр и ограничения по IP
- Поддержка внешнего API сайта
- Поддержка IPv6
Это если кратко. Например, модули и плагины ещё поддерживают зависимости (могут что-то требовать, с чем-то конфликтовать).
Компоненты устанавливаются тоже из phar архивов, которые если открыть напрямую покажут не установщик, а свой readme. Компоненты и система обновляются из тех же установщиков.
Всё это открыто и под дружелюбной MIT лицензией доступно всем желающим на GitHub, там же в wiki документация на английском.
https://github.com/nazar-pc/CleverStyle-CMS
Часть независимых, но полезных функций вынесена и доступна отдельно, будет полезена любому PHP разработчику:
https://github.com/nazar-pc/Useful-PHP-Functions
Это самые простые вещи, под данную CMS можно писать как предельно просто, так и немного сложнее.
Статья получилась не очень богатой на реальные примеры, если интересуют отдельные аспекты: разработка API сайта, работа с БД, роутингом, что-то ещё – напишу отдельную статью с простыми рабочими примерами.
Спасибо за внимание, буду рад любой обоснованной критике и пожеланиям, в состоянии Alpha каждый может повлиять на то, какой система будет в будущем.
Автор: nazarpc