Тревожный вопрос, как же организовать общение между 1С и базой сайта?
Рассмотрим вариант, когда мы будем использовать импорт и экспорт данных в формате 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);
}