Рассмотрим вариант, когда мы будем использовать импорт и экспорт данных в формате DBF.
Часть 1. Импорт в базу нашего сайта.
Экспорт из 1С это делается щелчками мыши, вдаваться в подробности не будем, мы не одинэсники.
Как импортировать DBF файл и распрасить его?
Приведем пример DBF файла. В нем структура такая:
ARTICUL, NAME, GROUP1, GROUP2, GROUP3, GROUP4, REMAINS, PRICE (и дополнтельные поля в зависимости от поставленной задачи и товаров)
ARTICUL — идентификатор товара
NAME — его название
GROUP1-GROUP4 — это категории товара. Цифры обозначают уровень вложенности и дают намек на структуру категорий.
REMAINS — остатки
PRICE — цена
Т.е. тут нет категорий, тут только товары, а пренадлежность и вложенность в категории определяется параметрами GROUP1-GROUP4.
Их и надо использовать для построения дерева и привязки к ним.
В php существуют инструменты для работы с такими файлами — dbase.
Открываем файл для чтения (read-only — это 0) с помощью функции dbase_open и подсчитываем количество записей.
$db = dbase_open($file, 0);
if ($db) {
$rows = dbase_numrecords($db);
print 'Найдено товаров в файле: ' . $rows;
}
Обращу внимание, что нумерация записей в dbf файле начинается не с 0, а с 1.
Поэтому, при обходе файла в цикле, мы начнем с 1.
Для получения данных о записе будем использовать dbase_get_record_with_names, которая возвращает ассоциативный массив, где ключи — названия полей.
Сначала позаботимся о структуре категорий нашего каталога. Допустим это будет простое дерево по parent_id
CREATE TABLE IF NOT EXISTS `structure` (
`id` int(11) unsigned NOT NULL auto_increment,
`parent_id` int(11) unsigned default NULL,
`name` varchar(255) NOT NULL default '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 PACK_KEYS=0 AUTO_INCREMENT=1;
Сразу же определимся со структурой таблицы с товарами:
CREATE TABLE IF NOT EXISTS `goods` (
`id` int(11) unsigned NOT NULL auto_increment,
`parent_id` int(11) unsigned default NULL,
`articul` int(11) unsigned default NULL,
`name` varchar(255) NOT NULL default '',
`GROUP1` varchar(255) NOT NULL default '',
`GROUP2` varchar(255) NOT NULL default '',
`GROUP3` varchar(255) NOT NULL default '',
`GROUP4` varchar(255) NOT NULL default '',
`remains` int(11) unsigned default NULL,
`price` float(11,2) default NULL,
UNIQUE KEY (`articul`),
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 PACK_KEYS=0 AUTO_INCREMENT=1;
Данные из полей GROUP1-GROUP4 нам понадобятся при экспорте из нашей базы (чтобы облегчить жизнь).
Итак, обходим наши данные:
for ($i=1; $i<=$rows; $i++) {
// в $row содержится запись
$row = dbase_get_record_with_names($db, $i);
// дальше работаем с данными…
}
Обычно файлы очень большие, поэтому мы сделаем поэтапную разбивку по 100 записей за 1 заход:
$start = isset($_GET['start']) ? intval($_GET['start']) : 1;
$end = $start+99;
if ($end > $rows) $end = $rows;
Таким образом цикл у нас будет такой:
for ($i=$start; $i<=$end; $i++)
Ну вот и сам разбор данных, опеределние категорий, вложенностей и добавление товара в базу (или его обновление при наличии).
for ($i=$start; $i<=$end; $i++) {
$item = dbase_get_record_with_names($db, $i);
// установим первоначальное значение для parent_id нашего товара в ноль
$parent_id=0;
$groups = array();
/*
** Обычно, при импорте в dbf из 1С, кодировка будет cp866
** мы переведем её в обычную для себя — cp1251
*/
$groups[] = convert_cyr_string(trim($item['GROUP1']), "a", "w");
$groups[] = convert_cyr_string(trim($item['GROUP2']), "a", "w");
$groups[] = convert_cyr_string(trim($item['GROUP3']), "a", "w");
$groups[] = convert_cyr_string(trim($item['GROUP4']), "a", "w");
/*
** Определяем parent_id (категорию, к которой отнесем наш товар)
** для подробностей — смотрите функцию ниже
*/
$parent_id = DefineParent($groups);
$articul = $item['ARTICUL'];
$name = convert_cyr_string(trim($item['NAME']), "a", "w");
$remains = intval($item['REMAINS']);
$price = floatval($item['PRICE']);
/*
** Приведение типа у remains может отличаться
** здесь пример, когда осаток товара на складе — целое число
** может быть остаток float, например, когда это вес какой-либо продукции (2,45 кг резиновых членов)
** так что, тут по ситуации
*/
/*
** Дальше мы проверим, есть ли в базе товар с таким артикулом
** и в зависимости от этого мы его добавим, либо обновим его данные
*/
$query = "SELECT `id`
FROM `goods`
WHERE `articul`='" . mysql_real_escape_string($articul) . "'
LIMIT 1";
$sql = mysql_query($query) or die(mysql_error());
if (mysql_num_rows($sql)==1) {
$row = mysql_fetch_assoc($sql);
// Если товар уже имеется в базе, мы обновим его данные: цену и остаток на складе
$query = "UPDATE `goods`
SET
`price`='{$price}',
`GROUP1`='{$groups[0]}',
`GROUP2`='{$groups[1]}',
`GROUP3`='{$groups[2]}',
`GROUP4`='{$groups[3]}',
`remains`='{$remains}'
WHERE `id`={$row['id']}
LIMIT 1";
$sql = mysql_query($query) or die(mysql_error());
}
else {
// Если его нет, то добавим его!
$query = "INSERT
INTO `goods`
SET
`parent_id`={$parent_id},
`name`='{$name}',
`GROUP1`='{$groups[0]}',
`GROUP2`='{$groups[1]}',
`GROUP3`='{$groups[2]}',
`GROUP4`='{$groups[3]}',
`articul`='{$articul}',
`price`='{$price}',
`remains`='{$remains}'
";
$sql = mysql_query($query) or die(mysql_error());
}
}
dbase_close($db);
print 'Сделано ' . $end . ' из ' . $rows . '. ';
if ($end != $rows) {
print 'Продолжаем… <script type="text/javascript">setTimeout("document.location.href=\'import.php?start=' . ($end+1) . '\'", 1000);</script>';
}
function DefineParent($groups)
{
$parent_id = 0;
foreach ($groups as $group) {
if (!empty($group)) {
$group_name = trim($group);
/*
** Проверим, есть ли такая категория уже в нашей базе?
*/
$query = "SELECT `id`
FROM `structure`
WHERE `name`='" . mysql_real_escape_string($group_name) . "' AND `parent_id`={$parent_id}
LIMIT 1";
$sql = mysql_query($query) or die(mysql_error());
if (mysql_num_rows($sql)==1) {
//Если нашли, то вытаскиваем её id, это и будет наш parent_id
$row = mysql_fetch_assoc($sql);
$parent_id = $row['id'];
}
else {
/*
** Если нет такой категории, то её необходимо создать
** и взять id новой категории за parent_id
*/
$query = "INSERT
INTO `structure`
SET
`parent_id`={$parent_id},
`name`='" . mysql_real_escape_string($group_name) . "'";
$sql = mysql_query($query) or die(mysql_error());
$parent_id = mysql_insert_id();
}
}
else {
// Если категория пустая, то дальше идти нет смысла, возвращаем полученный parent_id
return($parent_id);
}
}
return($parent_id);
}