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

Сегодня вкратце расскажу о том, как я решал одну непростую задачку. Суть ее заключается в том, что мне надо было создать большую таблицу (98 колонок), но не просто так, а из полей имеющейся формы на одном сайте. То есть там уже есть имена полей (в итоге — колонок), лейблы этих полей (они пойдут в комменты колонок и человекопонятные названия полей в итоговой форме). Само собой вручную создавать таблицу, все 98 колонок и т.п. — это во-первых, лениво, а во-вторых, не очень продуктивно. Я решил все это сделать программно. Вот это здесь и опишу вкратце. Краткий план работ. План простой: Посредством jQuery собрать информацию о полях (названия, лейблы, дефолтовые значения), упаковать это все в JSON. Средствами PHP на своем уже сервере преобразовать JSON в массив исходных данных. Сгенерировать и записать модель xPDO-объекта Из описания 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 имеются методы изменения таблиц, удаления и добавления колонок и т.п. Но это уже тема для отдельного топика.

А вот это очень полезная штука. Спасибо, вот и тема, которую можно потыркать на праздниках)

Пожалуйста.