В рамках проектов Robodile и IGD разработана новая разновидность системы управления контентом Kion CMS+L, в которой миграция данных, структур данных и сценарии по их обработке реализуются за счет использования языка Lua. Для этих целей были написаны трансляторы из Lua в PHP/JavaScript и обратно. Помимо этого предусмотрено множество дополнительных возможностей.
Kion CMS+L — это разновидность Kion CMS с поддержкой Lua. Kion CMS является высокопроизводительной системой управления контентом, написанной на стандартной связке: PHP/MySQL/CSS/JavaScript(jQuery). Вариант с использованием Lua предполагает дополнительные возможности по сериализации данных, их последующей обработке на сервере и/или клиенте, написанию сценариев действий.
Важно понимать, что язык Lua в рамках Kion CMS+L не используется в своем классическом представлении, которое вы можете сейчас встретить в разработках компьютерных игр и десктопных/серверных приложений. В Kion CMS+L используется только синтаксис Lua и типы данных плюс специфика работы с ними. Об использовании интерпретатора и компилятора уровня LuaJIT речь не идет.
Для интеграции Lua в Kion CMS достаточно подключить два файла: kion_lua.php и kion_lua.js. Эти файлы позволяют работать с Lua-кодом соответственно в PHP и JavaScript.
Зачем это нужно?
- Хранение и миграция структур данных (без SQL).
- Написание сценариев обработки данных. Миграция методов обработки данных.
- Шифрование/дешифрование данных.
- Синхронизация данных.
- Расширенные возможности клиентской части за счет интеграции Lua и JavaScript.
Нужно отметить главную особенность данного решения: из PHP или JavaScript в Lua можно транслировать только данные и их структуру. Из Lua происходит более широкое по возможностям преобразование, а именно, трансляция кода, в рамках которой помимо самих данных можно передавать в PHP или JavaScript пользовательские функции, циклы, условные операторы, базовые С-функции (например, для работы со строками). При трансляции они превращаются в стандартные конструкции языков PHP и JavaScript. Другими словами, если вы написали функцию обработки массива на Lua, она с сохранением всех внутренних алгоритмов и параметров преобразуется в идентичные на PHP и JavaScript.
Если говорить о работе со структурами данных, то встраивание Lua можно сравнить с использованием YAML, который хорошо знаком программистам Symfony, а также с JSON. Но при этом в самом файле сценария (Lua-файле) вы можете не только хранить данные, но и прописывать условия их обработки.
Язык Lua очень удобен и прост в программировании, является С-подобным, имеет ряд уникальных особенностей. Одна из них — это тип данных table, который подразумевает, по существу, ассоциативные массивы с данными гетерогенного типа. В качестве ключей и значений элементов могут выступать любые типы данных (в т.ч. другие таблицы, функции, которые в данном языке также являются отдельным типом и т.п.), кроме nil (неопределенный тип).
Также на уровне Lua вы можете производить взаимодействие с другими Lua-файлами (импорт), таким образом можно собирать более сложные структуры.
Для демонстрации того, как это работает, покажем несколько внутренних механизмов Kion CMS+L.
Базовые функции трансляции и выборки
Для трансляции/перемещения кода без шифрования предусмотрено семь базовых функций:
- lua_add(data, tablename); - для PHP и JS.
- lua_add_to_file(data, tablename, filename); - для PHP и JS.
- lua_parse(variablename); - для PHP и JS.
- lua_parse_file(filename); - для PHP и JS.
- lua_get_element(elementname, variablename); - для PHP и JS.
- lua_get_element_from_file(elementname, filename); - для PHP и JS.
- lua_delete_file(filename); - только для PHP.
Преобразование данных из PHP и JavaScript в Lua-строку производится с помощью функции lua_add(data, tablename), в которой может использоваться два входящих аргумента — переносимый массив с данными и имя таблицы(массива), в которую эти данные помещаются. Приведем пример для PHP:
$lua_array = array("foo" => "bar");
$lua=lua_add($lua_array, ‘larr’);
Сформированная Lua-строка после преобразования будет иметь вид:
larr={foo=”bar”}
Функцию lua_add() можно использовать бесконечное число раз, добавляя или модифицируя данные:
$lua_array = array("bar" => "foo");
$lua=lua_add($lua_array, ‘larr’);
Сформированная/преобразованная lua-строка будет выглядеть:
larr={foo=”bar”, bar=”foo”}
Если элемент указанного массива с соответствующим ключом уже существует, его значение при использовании lua_add() переписывается.
Если вы передаете пустое значение, соответствующий элемент массива (таблицы) автоматически удаляется.
$lua_array = array("foo" => "");
$lua=lua_add($lua_array, ‘larr’);
В результате lua-строка преобразуется в:
larr={bar=”foo”}
Функция lua_add_to_file(data, tablename, filename) работает аналогично lua_add(), только запись данных производится в указанный lua-файл (кодировка UTF-8). Имеет три входящих аргумента (требуемые к переносу данные, имя таблицы(массива), в которую эти данные помещаются, и имя файла). Вызов выглядит так:
lua_add_to_file($lua_array, ‘larr’, 'lua_data.lua');
В качестве имени файла можно указать адрес url, начинающийся с «http://» или «https://».
Для случаев изменения значений существующих элементов таблиц, а также удаления этих элементов функция работает идентично lua_add().
Для обратной операции в PHP и JavaScript используются две функции: lua_parse(variablename) и lua_parse_file(filename). Обратное преобразование подразумевает непосредственно трансляцию структуры данных и функций (в случае файла) из Lua в PHP или в JavaScript, в зависимости от того, откуда оно вызывается.
Для функции lua_parse_file(filename) в качестве имени файла можно указать адрес url, начинающийся с «http://» или «https://».
Для получения определенных элементов из таблиц используются две функции lua_get_element(variablename, elementname) и lua_get_element_from_file(elementname, filename).
Первая из них читает данные из строки, в аргументах указываются: конкретно элемент, который нужно заполучить и имя переменной, содержащей lua-строку. Пример для PHP:
$lua_array = array("foo" => "bar");
$lua=lua_add($lua_array, ‘larr’);
$lua_v1= lua_get_element(larr, $lua) //заберет весь массив из таблицы larr в строке $lua
$lua_v2= lua_get_element(larr[“foo”], $lua) //заберет значение элемента larr[“foo”] в строке $lua
Как видите, данная функция очень удобна, то есть она может забирать не только конкретные значения, но и массивы. Если в larr[“foo”] будут содержаться элементы следующего уровня, например, larr[“foo”] [1], larr[“foo”] [2] и т.п., то, соответственно, в переменную $lua_v2 загрузится опять же массив.
Функция lua_get_element_from_file(elementname, filename) работает аналогично, с той лишь разницей, что в качестве второго аргумента нужно указать не имя переменной, содержащей строку, а название файла или его url, начинающийся с «http://» или «https://».
В рамках Kion CMS+L может использоваться обратимое шифрование данных ключом, соответственно, для этого разработаны специальные функции, аналогичные описанным выше, но имеющими префикс «s» в наименовании, и в них добавлен еще один аргумент — ключ шифрования:
- slua_add(key, data, tablename); - для PHP и JS.
- slua_add_to_file(key, data, tablename, filename); - только для PHP.
- slua_parse(key, variablename); - для PHP и JS.
- slua_parse_file(key, filename); - для PHP и JS.
- slua_get_element(key, elementname, variablename); - для PHP и JS.
- slua_get_element_from_file(key, elementname, filename); - для PHP и JS.
Алгоритмов шифрования предусмотрено всего пять, включая Blowfish. Переключение между ними производится в настройках kion_lua.php и kion_lua.js.
Синхронизация данных
Довольно часто можно встретить ситуацию, когда необходимо синхронизировать данные, разнесенные по разным сайтам на разных серверах. Для этого разработаны четыре универсальные функции (только для PHP):
- lua_sync_files (filename1, filename2)
- slua_sync_files (key, filename1, filename2)
- lua_sync_batch (filename1, filename2, depth)
- slua_sync_batch (key, filename1, filename2, depth)
Как понятно, речь идет о работе с обычными и зашифрованными файлами (для второй и четвертой функций нужно указать общий ключ шифрования).
Что касается имен файлов, то подойдут как обычные относительные ссылки, так и url, начинающиеся с «http://» или «https://».
Функции работают следующим образом: из двух файлов выбирается наиболее свежий по дате, и более старый заменяется на новый. Если одного из файлов нет, то другой копируется в указанное место под введенным именем.
lua_sync_files() и slua_sync_files() работают только с двумя файлами. Эти функции выгодно использовать для случаев, например, когда пользователь загрузил новую фотографию, и в один из файлов данных добавилась ее ссылка и т.п. Пример:
lua_sync_files (‘/data1.lua’, ‘http://sitename.ru/luascripts/data1.lua’);//изменили файл данных на втором сервере
lua_sync_files (‘/picture1.jpg’, ‘http://sitename.ru/images/picture1.jpg’);//загрузили картинку на второй сервер
Если имена файлов одинаковы, и таких много, вы можете использовать две функции пакетной обработки — lua_sync_batch() и slua_sync_batch(). Для этого достаточно поставить «*» в имени вместо тех символов, которые меняются. Также добавлен еще один аргумент — глубина сканирования, который указывается в цифрах. Если указан 0, то вложенные папки относительно указанных файлов не сканируются, сверка идет только в узлах, где эти файлы расположены, 1 — сканируются и дочерние папки. Если с одной из сторон какой-либо файл отсутствует, с другой копируется имеющийся.
Пример:
lua_sync_batch (‘/*.lua’, ‘http://sitename.ru/luascripts/*.lua’, 0);
Как понятно из написанного, синхронизация может затрагивать не только файлы с расширением lua, но и любые другие файлы.
Таймлайн
На данный момент Kion CMS+L тестируется на коммерческих проектах, в будущем планируется выложить файлы интеграции в свободный доступ.
Владимир Бодов a.k.a. Кристофер
![Версия для печати Версия для печати](https://www.kv.by/sites/all/modules/print/icons/print_icon.png)
Комментарии
Нда, настало время, когда в статье вроде как про программирование я вижу кучу новых слов. Ну, и вообще в статьях по IT, кстати.
Мысль в том, что выросло IT. В полноценную отрасль, где не может быть универсалов.
Ну, сама идея использовать Lua была не спроста. Был запрос от немцев, им нужно было разработать безопасную CRM с многосайтовостью. То есть, много форм, которые размещаются на разных сайтах и даже разных CMS, но они имеют прямой и обратный траффик по лидам, сделкам и т.п. Я уже тогда подумал о Lua. Потом один сайт, который базируется на моей CMS, попросил синхронизацию с другим сайтом в другом регионе (на другом сервере и на другом сайте). В июне я начал писать синхронизатор, в ноябре были сделаны трансляторы Lua->PHP/JS и обратно. Почему был выбран именно Lua, а не С? Lua имеет динамическое приведение типов, то есть, он ближе к PHP и JavaScript, и может стать универсальным мостом, что и получилось. Все тесты - за:)
igd - на страничке http://www.igd.by/about/ нужно исправить забавную и двусмысленную очепятку "покупки придуктов Битрикс с 40% скидкой":) DNA для вашего веб-бизнеса - хороший слоган. Про необходимость lua, признаюсь, не понял ничего, но готов согласиться с авторитетом:)