Сегодня вкратце расскажу о том, как я решал одну непростую задачку. Суть ее заключается в том, что мне надо было создать большую таблицу (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 имеются методы изменения таблиц, удаления и добавления колонок и т.п. Но это уже тема для отдельного топика.
А вот это очень полезная штука. Спасибо, вот и тема, которую можно потыркать на праздниках)
Пожалуйста.