ФорумПрограммированиеПыхнуть хотите?F.A.Q. → Синхронизация базы сайта с базой 1С (экспорт, импорт). Часть 1 — Импорт.

Синхронизация базы сайта с базой 1С (экспорт, импорт). Часть 1 — Импорт.

  • md5

    Сообщения: 11960 Репутация: N Группа: в ухо

    Spritz 10 сентября 2008 г. 11:18

    Тревожный вопрос, как же организовать общение между 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);
    }
    все умрут, а я изумруд
  • md5

    Сообщения: 11960 Репутация: N Группа: в ухо

    Spritz 10 сентября 2008 г. 11:28, спустя 10 минут 5 секунд

    http://pyha.ru/articles/php/1c-dbf-import/
    все умрут, а я изумруд
  • Trej Gun

    Сообщения: 5305 Репутация: N Группа: в ухо

    Spritz 10 сентября 2008 г. 12:43, спустя 1 час 14 минут 43 секунды

    прикольно)
    я както делал базу сайта из mdb подключенного через odbc как источник данных
    работал кстати через адодб, очень скажу вам нормально получалось
  • sap

    Сообщения: 2701 Репутация: N Группа: Кто попало

    Spritz 11 сентября 2008 г. 19:35, спустя 1 день 6 часов 52 минуты

    А вообще возможно технически сделать так, чтобы базы синхронизировались автоматически по расписанию?
  • md5

    Сообщения: 11960 Репутация: N Группа: в ухо

    Spritz 11 сентября 2008 г. 20:51, спустя 1 час 15 минут 28 секунд


    А вообще возможно технически сделать так, чтобы базы синхронизировались автоматически по расписанию?
    конечно
    у кефирки спроси, как ставить таймеры ;)

    я не силен в 1С, более того - я его только видел несколько раз не ближе 1 метра + коробки от него видел и поэтому не знаю, умеет ли он работать с мускулом и др. субд.
    У нас синхронизация происходит так:
    1С-ники каждые пол часа по ФТП заливают DBF файл (наверно же есть там спецсредства для этого…) а на стороне сервера у нас по крончеку скрипт разгребает его и обновляет мускульную базу

    ещё есть подобная схема, но там уже не DBF, а XML, но это уже не из этого фака…
    все умрут, а я изумруд
  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 8 декабря 2009 г. 21:34, спустя 453 дня 1 час 42 минуты

    Добрый вечер. Может быть испорчу своим вопросом всю тему, но все же. Подскажите пожалуйста, если кто-то знает, как все-таки из 1С экспортировать данные в DBF. Сам пробовал, но нашел только как снять дамп всей БД, а нужно только кокретные прайсы. Искал на форумах других, но там видимо только для мега знатоков. Видел какие-то коды на руском языке… честно сказать ничего не понял.
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 8 декабря 2009 г. 21:47, спустя 13 минут 33 секунды

    Видел какие-то коды на руском языке… честно сказать ничего не понял.
    ты сука в россии живешь, так и программируй на русском!!! 1С - ДЛЯ ПАТРИОТОВ!
    Сапожник без сапог
  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 8 декабря 2009 г. 21:52, спустя 4 минуты 54 секунды


    Видел какие-то коды на руском языке… честно сказать ничего не понял.
    ты сука в россии живешь, так и программируй на русском!!! 1С - ДЛЯ ПАТРИОТОВ!


    Ты сука умных мыслей нет, сиди селекты из бд делай
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 8 декабря 2009 г. 21:57, спустя 5 минут 1 секунду

    smv, ты к чему?
    Сапожник без сапог
  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 8 декабря 2009 г. 21:58, спустя 1 минуту 1 секунду


    smv, ты к чему?


    а ты к чему?
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 8 декабря 2009 г. 22:04, спустя 5 минут 42 секунды

    видимо моему собеседнику при зачатии не повезло на ген юмора :)
    Спустя 9 сек.
    проехали
    Сапожник без сапог
  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 8 декабря 2009 г. 22:05, спустя 1 минуту 30 секунд


    видимо моему собеседнику при зачатии не повезло на ген юмора :)
    Спустя 9 сек.
    проехали


    Я задал помоему вполне конкретный вопрос. И буду очень благодарен если получу на него конкретный ответ. Давай не будм за зря сотрясать воздух… ок? В юморе хочеш потягаться? тогда тебе в аншлаг.
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 8 декабря 2009 г. 22:07, спустя 1 минуту 59 секунд

    smv, не дали? :)
    Сапожник без сапог
  • smv

    Сообщения: 236 Репутация: N Группа: Кто попало

    Spritz 8 декабря 2009 г. 22:10, спустя 2 минуты 17 секунд


    smv, не дали? :)

    вау… ха ха ха… чуть со стула не упал. Видать ты в аншлаге часто зависаеш… а ты случаем не регина дубовицкая? а?
  • adw0rd

    Сообщения: 22959 Репутация: N Группа: в ухо

    Spritz 8 декабря 2009 г. 22:16, спустя 6 минут

    smv, так сними дамп и вытащи свои прайсы
    https://smappi.org/ - платформа по созданию API на все случаи жизни

Пожалуйста, авторизуйтесь, чтобы написать комментарий!