Николай Ланец
8 мая 2013 г., 4:43

Генерация map-файла объекта и создание его таблицы средствами xPDO

Сегодня вкратце расскажу о том, как я решал одну непростую задачку. Суть ее заключается в том, что мне надо было создать большую таблицу (98 колонок), но не просто так, а из полей имеющейся формы на одном сайте. То есть там уже есть имена полей (в итоге — колонок), лейблы этих полей (они пойдут в комменты колонок и человекопонятные названия полей в итоговой форме).
Само собой вручную создавать таблицу, все 98 колонок и т.п. — это во-первых, лениво, а во-вторых, не очень продуктивно. Я решил все это сделать программно. Вот это здесь и опишу вкратце.
Краткий план работ.
План простой:
  1. Посредством jQuery собрать информацию о полях (названия, лейблы, дефолтовые значения), упаковать это все в JSON.
  2. Средствами PHP на своем уже сервере преобразовать JSON в массив исходных данных. Сгенерировать и записать модель xPDO-объекта
  3. Из описания xPDO-объекта создать конечную таблицу.
Этап первый. Собираем данные формы и упаковываем в JSON.
В FireBug-е на нужной мне странице выполнил такой код (jQuery там был, что не удивительно):
var fieldsSer = $('Form').serializeArray(); // Собираем все поля формы var fields = {}; var name; for(var i in fieldsSer){ el = fieldsSer[i]; name = el.name fields[name] = el; // Находим лейбл для поля (у всех полей id совпадало с name, потому было просто найти лейблы для них) label = $('[for='+ name +']') text = label.text(); fields[name].label = text; } // Собираем полученный объект в JSON JSON.stringify(fields);
Этап второй. Из JSON-строки формируем
<?php $className = 'myClass'; $fields = array(); $fieldMeta = array(); // Формируем путь до map-файла, в который будем записывать конечные данные $file = MODX_CORE_PATH .'components/mypackage/model/mypackage/mysql/myclass.map.inc.php'; $arr = $modx->fromJSON($JSON); // Преобразуем JSON-строку в массив // Обрабатываем все поля foreach($arr as $field => $meta){ $value = $meta['value']; $dbtype = "varchar"; $phptype = "string"; $precision = 255; $null = true; $required = false; if(is_numeric( $value)){ $dbtype = "int"; $phptype = "integer"; $precision = 11; } if($value == ''){ $value = NULL; } $fields[$field] = $value; $label = trim($meta['label']); $label = preg_replace("/[\r\n]+/", "", $label); $label = preg_replace("/ {2,}/", " ", $label); if(!empty($label) && strpos($label, '*')){ $required = true; } $fieldMeta[$field] = array( 'comment' => $label, 'dbtype' => $dbtype, 'precision' => $precision, 'phptype' => $phptype, 'null' => $null, 'default' => $value, 'required' => $required, 'in_form' => true, ); } /* Готовим и записываем конечное описание объекта */ $xpdo_meta_map = array ( 'package' => 'myPackage', 'version' => '1.1', 'table' => 'mytable', 'extends' => 'xPDOSimpleObject', 'fields' => $fields, 'fieldMeta' => $fieldMeta, ); // Обратите внимание на функцию var_export - очень важная и полезная штука $fileContent= "<?php\n\$xpdo_meta_map['$className']= " . var_export($xpdo_meta_map, true) . ";\n"; // Записываем полученный массив в файл $modx->cacheManager->writeFile($file, $fileContent);
Этап третий. Из модели объекта создаем таблицу.
Здесь уже все просто и стандартно.
$manager = $modx->getManager(); // Создаем таблицу объекта // Таблицы не должно быть изначально, этот метод только создает новую таблицу, // не обновляет и не грохает имеющуюся $manager->createObjectContainer('myClass');
Немного лирики.
Вообще описанный метод для меня сегодня был практически единственным приемлемым в моей ситуации. У меня многое в проекте завязано именно на map-описании объекта (Туда же записать можно все, что угодно. В частности, у меня там записаны комментарии, которые в итоге подставляются в названия полей в форме, а в базе данных они просто необходимы, чтобы разобраться в массе всяких «интуитивно-понятных» полей). И у меня был вариант или создавать таблицу, и потом из нее генерить map-файл, или наоборот, сначала создать map-файл, а потом уже создать таблицу. Я выбрал именно второй, так как описанное здесь — это только начало. Еще предстоит пройтись по всем полям, актуализировать типы данных до конца, указать длину полей и т.д. и т.п. И в этом плане с файлом работать гораздо проще, чем с таблицей, к тому же еще и гораздо быстрее. А ничего не стоит на этапе разработки грохнуть всю таблицу и в две строчки создать новую.
А еще следует сразу отметить, что в xPDO имеются методы изменения таблиц, удаления и добавления колонок и т.п. Но это уже тема для отдельного топика.
А вот это очень полезная штука. Спасибо, вот и тема, которую можно потыркать на праздниках)

Добавить комментарий