Встала передо мной задача: перенести имеющийся сайт (назовем его оригинальным) с неизвестной мне CMS (смотрел сервисом http://2ip.ru/cms/) на CMS 1C-Битрикс Управление сайтом "Малый бизнес" (назовем его как сайт-приемник). У CMS оригинала нет никаких средств по выгрузке каталога, поэтому пришлось писать свой обработчик. [spoiler] Был доступ к PhpMyAdmin оригинального сайта и доступ в его админку, чтоб понять взаимосвязь между всеми полями каталога и таблицами базы данных. В результате - нашел интересующую меня таблицу.
Для простоты обработки данных сделал бекап базы с сайта и получил sql-файлик.
Далее - берем битриксовую виртуальную машину и устанавливаем ее на VM Player.
Проводим установку стандартной демки интернет-магазина на малом бизнесе.
Устанавливаем PhpMyAdmin (см. тут) и в нем поднимаем бекап ( просто я не на столько серьезный специалист в работе с Linux, поэтому пользовался данным средством. Знатоки Linux могут развернуть бекап базы и средствами линуха). Разворачиваем созданный на оригинальном сайте бекап базы.
Дальше переходим к разработке скрипта, который будет проводить перенос данных.
Сразу предупреждаю. Заказчики решили сделать всю разработку сначала на стандартном шаблоне битрикса, поэтому старался максимально использовать имеющиеся данные, в том числе и инфоблок с каталогом (единственное - добавил нужные мне поля).
Разделов на сайте - не много, поэтому не стал заморачиваться с созданием скрипта, который создаст мне разделы, а просто вручную внес их в инфоблоке.
В будущем скрипте прописываю функцию, в которой через switch прописываю взаимосвязи кодов разделов оригинального сайта и сайта-приемника.
Пишем аналогичные функции по обработке других свойств, которые описывают каталог списками выбора (разные цветовые характеристики, фиксированные размеры и т.п.)
Определяем 2 массива: массив $items - будет собирать данные из базы и $unic_codes - расскажу позже о нем.
Делаем соединение с базой, выгруженной из оригинального сайта.
//соединение с базой данных при помощи функции mysql_connect() //в аргументах функции укажите имя сервера, логин и пароль. $db = mysql_connect("localhost","ваш_пользователь","ваш_пароль"); //функция mysql_select_db() выбирает текущую //базу данных с именем базы с данными с оригинального сайта if(!mysql_select_db("ваша_база" ,$db)){echo "not connected"; die;} //функция mysql_query() выполняет запрос на выборку данных //результирующий набор данных хранится в переменной $sql //LIMIT ограничение на количество выгружаемых полей $sql = mysql_query("SEL ECT * FR OM `таблица_с_каталогом` LIMIT 0, 1000" ,$db); //закрытие соединение (рекомендуется)*/ mysql_close($db);
Небольшие пояснения:
У меня в оригинальной базе 2074 единиц товара. При попытке перенести все за один раз - просто падал сервер (Для сервера выделял всего 512 метров ОЗУ), поэтому делал обрезки по 1000 и еще 1074 единиц (скрипт просто 2 раза запускал....)
Дальше обрабатываем полученную выгрузку:
while ($rows = mysql_fetch_row($sql)) $item=array( "Cur_ID"=>$rows[0], /*текущий ИД*/ "Cat_id"=> SetSection($rows[2]), /*категория*/ .... тут разные свойства .... "code"=>$rows[8], /*Артикул*/ "el_CODE"=>unic_it(translit_it($rows[8])), "name"=>$name, /*Название*/ "cost"=>$rows[10], /*Стоимость*/ "descr_short"=>$rows[17], /*Анонсовое описание*/ "descr"=>$rows[18], /*Детальное описание*/ "photo"=>$det_picture, /*Детальное изображение*/ "photo"=>$an_picture, /*Анонсовое изображение*/ ) ; $items[]= $item; }
Пояснения:
Для себя, для удобства решил пользоваться ассоциативным массивом (если хотите - можете и обычный использовать....). В переменную $item закидываем в соответствующие поля значения из базы (смотрел на нужные номера полей через print_r() ) а потом эту переменную добавляем ко всем остальным. По поводу поля el_CODE: это будет символьным кодом нашего товара. В него заливаю имя товара (транслитерированное), которое сразу проверяю на уникальность (столкнулся с тем, что есть несколько одинаковых по названию товаров....). Вот функция проверки на уникальность:
function unic_it($code){ //проверяем выбранный код на уникальность global $unic_codes; if (in_array($code, $unic_codes)){ $code = $code."a"; } $unic_codes[]=$code; return $code;}
Данная функция на входе получает код. Ищет его в глобальном (для данного скрипта) массиве $unic_codes и если находит - добавляет к коду символ "а". Полученный в результате код добавляется к списку уникальных. Поля с изображениями делал переменными, т.к. мне нужно было делать сложные манипуляции с выбором изображения.
В общих чертах данные переменные выглядят так:
$det_picture=CFile::MakeFileArray("абсоллютный путь к папке с изобржениями на оригинальном сайте".$rows[19]);
В базе хранилось только имя изображения, а все изображения - в одной общей папке. Поэтому по имени изображения нахожу его на оригинальном сайте и создаю файловый архив данного изображения.
Вот в принципе и все. Массив с записями из базы готов.
Теперь нужно его занести в каталог сайта-приемника.
foreach($items as $item): $el = new CIBlockElement; //определяем новый элемент $PROP = array(); //задаем его свойства $PROP[1] = <значение>; и другие свойства $arLoadProductArray = Array( "MODIFIED_BY" => $USER->GetID(), "IBLOCK_SECTION_ID" => $item["Cat_id"], "IBLOCK_ID" => 3, /*тут ставите свой инфоблок*/ "PROPERTY_VALUES"=> $PROP, "NAME" => $item["name"], "CODE" => $item["el_CODE"], "DETAIL_PICTURE" => $item["photo"], "PREVIEW_PICTURE" => $item["photo_small"], "ACTIVE" => "Y", ); if($PRODUCT_ID = $el->Add($arLoadProductArray, false, false, true)) { //echo "New ID: ".$PRODUCT_ID."<br />"; //добавляем количество товара и его цену $PRICE_TYPE_ID = 1; //базовая валюта $arFields = Array( "PRODUCT_ID" => $PRODUCT_ID, "CATALOG_GROUP_ID" => $PRICE_TYPE_ID, "PRICE" => $item["cost"], "CURRENCY" => "UAH" /*код валюты*/ ); $res = CPrice::GetList( array(), array( "PRODUCT_ID" => $PRODUCT_ID, "CATALOG_GROUP_ID" => $PRICE_TYPE_ID ) ); if ($arr = $res->Fetch()) { CPrice::Update($arr["ID"], $arFields); } else { CPrice::Add($arFields); } //добавляем количество на складе (по умолчанию = 1) $arFields = array( "ID" => $PRODUCT_ID, "QUANTITY"=>1 ); if(CCatalogProduct::Add($arFields)) //echo "Добавили параметры товара к элементу каталога ".$PRODUCT_ID.'<br>'; continue; else echo 'Ошибка добавления параметров для '.$PRODUCT_ID.'<br>'; // конец добавления элемента } else { echo "Error: ".$el->LAST_ERROR; echo "<pre>"; print_r($arLoadProductArray); echo "</pre>"; } endforeach;
Теперь по порядку: В цикле перебираем все элементы массива. На каждой итерации создаем ассоциативный массив $arLoadProductArray, который описывает все поля вновь создаваемого элемента.
Дальше если добавление прошло удачно - нужно задать стоимость данного товара и его количество.
Все это достаточно хорошо расписано в документации продукта, поэтому сильно расписывать не буду. Кого заинтересует - спрашивайте по коду - буду рассказывать.
Не забудьте в визуальной части сайта отметить добавленные вами свойства, чтобы пользователи тоже смогли их увидеть:)
А можно еще переносить ID товара из исходной системы в поле XML_ID приемной При этом, проверяя XML_ID, можно использовать не только Add но и Update и выполнять импорт неоднократно если часть данных когда то упуститься - можно "дополнить"
отличное решение. как-раз сейчас делаю очередной перенос и для старого ИД завел свойство инфоблока. и как я не додумался до XML_ID ... называется "век живи, век учись"
отличное решение. как-раз сейчас делаю очередной перенос и для старого ИД завел свойство инфоблока. и как я не додумался до XML_ID ... называется "век живи, век учись"
а вот не факт, что вы сделали неверно то,как вы поступили - тоже решение
и у него есть плюс даже если XML_ID вдруг надо будет поменять (например синхронизировать с 1С), у вас все равно останется на хранении исходный старый ИД товара
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».