[MODX] Импорт и экспорт в MiniShop2. Реализация 1

Для того чтобы сделать экспорт (выгрузку) используем пакет catalogfill.

Конфигурация для экспорта: Показать

//разбивка по столбцам при импорте и экспорте (content|tv|category)
$cf_config['content_row'] = array(
    array('RES_category',array(13,'category')),//3 - ID шаблона категории
    array('RES_subcategory',array(13,'category')),//3 - ID шаблона подкатегории
    array('RES_pagetitle',array('pagetitle','content')),
    array('RES_introtext',array('introtext','content')),
    array('RES_content',array('content','content')),
    array('RES_uri',array('uri','content')),
    array('RES_alias',array('alias','content')),



    // Товар TV
    array('TV_articul', array(16, 'tv')), // id Дополнительного поля
    array('TV_available', array(32, 'tv')),
    array('TV_id_similar', array(18, 'tv')),
    array('TV_main_img', array(14, 'tv')),
    array('TV_mark', array(19, 'tv')),
    array('TV_other_img', array(17, 'tv')),
    array('TV_price', array(15, 'tv')),
    array('TV_price_1', array(35, 'tv')),
    array('TV_price_10', array(22, 'tv')),
    array('TV_price_100', array(24, 'tv')),
    array('TV_price_5', array(21, 'tv')),
    array('TV_price_50', array(23, 'tv')),
    array('TV_price_500', array(25, 'tv')),
    array('TV_specification', array(34, 'tv')),



    array('TV_desc', array(30, 'tv')),
    array('TV_key', array(29, 'tv')),
    array('TV_tit', array(28, 'tv')),
    
    
    array('HitsPage',array(31,'tv'))
);

//значения по умолчанию при импорте или проверка при экспорте
$cf_config['imp_content_default'] = array(
    'content' => array(
        'published' => 1,
        'template' => array(4)
        //'createdon' => strtotime("now")
    ),
    'tv' => array(
        //7 => 0
    )
);

//первая строка - названия полей
$cf_config['include_captions'] = true;

//число товаров импортируемых за один раз (загрузка по группам). 0 - не ограничивать.
$cf_config['batch_import'] = 300;

//разбивать по категориям
$cf_config['include_categories'] = true;

//удалять дочерние категории при очистке и обновлении каталога
$cf_config['delete_subcategories'] = true;

//по какому полю проверять соответствие товара при обновлении. false - не проверять (очистка категории при обновлении).
$cf_config['imp_chk_field'] = 'pagetitle';

//проверять соответствие товара при обновлении по значению TV. Указать ID TV. false - не проверять (очистка категории при обновлении).
$cf_config['imp_chk_tvid_val'] = false;

//Добавлять товары, которые не найдены при обновлении по TV (imp_chk_tvid_val) или полю (imp_chk_field)
$cf_config['imp_if_not_exist'] = true;

//удалять HTML-теги при экспорте
$cf_config['exp_strip_tags'] = false;

//автоматически генерировать псевдоним (alias) при импорте
//false - выключено; true - генерировать с переводом в транслит; 'notranslit' - генерировать без перевода в транслит.
$cf_config['imp_autoalias'] = true;

//Изменить значения поля для всех вложенных товаров до начала импорта.
//Например можно отменить публикацию для всех товаров и публиковать только те, которые есть в новом прайс-листе.
//первый массив - какие поля и на какие значения менять, второй массив - условия которые нужно проверять (можно сделать пустым)
$cf_config['imp_before_change'] = false;//'[{"tv.inventory":0},{}]';//'[{"published":0},{"tv.pricename":"Поставщик1"}]';//false - для отмены

//удалить файл после экспорта (скачивания)
$cf_config['exp_delete_file'] = false;

//кодировка CSV-файла при экспорте
$cf_config['exp_csv_charset'] = 'UTF-8';//'windows-1251'

//Импортировать (обновлять) пустые значения
$cf_config['imp_empty'] = true;

//Имя файла процессора, который использовать для импорта. Если пусто, используется стандартный процессор "import".
$cf_config['imp_custom_processor'] = '';

//путь (xpath) в XML структуре до товаров
$cf_config['imp_xml_itemsparent_path'] = '';//'/catalog/shop/offers'

//Структура XML файла для импорта
$cf_config['imp_xml_structure'] = '';

//тестирование конфигурации (без записи в БД)
$cf_config['imp_testmode'] = false;

//функция для фильтрации значений при ИМПОРТЕ
function filter_import($value_arr){
    $output_arr = $value_arr;
    /*
    if(isset($output_arr['content']['pagetitle']))
        $output_arr['content']['pagetitle'] = mb_strtoupper($output_arr['content']['pagetitle'], 'UTF-8');
    */
    return $output_arr;
}


//функция для фильтрации значений при ЭКСПОРТЕ
function filter_export($value_arr,$doc_id=0){
    $output_arr = $value_arr;
    //var_dump($value_arr,$output_arr);
    //exit;
    /*
    if(isset($output_arr['price']))
        $output_arr[1] = floatval($output_arr[1]) - 200;
    */
    return $output_arr;
}
    
Скрыть

Экспортируем в CSV

Так как я переносил еще и картинки, и имел доступ к обоим серверам, то я просто скопировал их с одного сайта на другой через FTP клиент. Для этого я использовал вот этот нехитрый метод

Далее делаем импорт — загрузку полученных данных в магазин. Для этого я уже не использовал это дополнение, так как хотел четко контролировать что куда помещать.

В системе нового сайта создаем сниппет с поэтическим названием import_x

Содержимое скрыто под спойлер. Показать
set_time_limit(0);


// !!! Отредактировать
$parent_id = 2722;
$template_id = 3;
$csv_file = "exp_10_03_18__12_53_40.csv";


// Получаем список УЖЕ импортированных нами ресурсов
$q = $modx->newQuery('modResource');
$q->select(array('pagetitle'));
$q->where(array(
    'template' => $template_id,
    'parent' => $parent_id
    ));
$q->limit(0);
$q->prepare();
$q->stmt->execute();
$res = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
$alredy_imp = array();
foreach($res as $v){
    $alredy_imp[] = $v['pagetitle'];
}


// Обрабатываем файл CSV
$csv_file_open = fopen($csv_file, 'r');

// Формируем удобочитаемый массив с данными из CSV:
$arr_keys = array();
$prod_array = array();

while ( ($data = fgetcsv($csv_file_open, 0, ";") ) !== FALSE ) {
    if($data[2] == "RES_pagetitle"){ // Таким странным образом определяем что это первая строка CSV файла
        $arr_keys = $data;
    }else{
        $temp_array = array();
        foreach($data as $k => $v){
            $temp_array[$arr_keys[$k]] = $v;
        }
        $prod_array[] = $temp_array;
    }
}
//print_r($prod_array);
//die;
$count = 0;
$hadErrors = false;
foreach($prod_array as $v){
    //print_r($v);
    
    $data = array();
    
    $data['class_key'] = 'msProduct';
    $data['pagetitle'] = $v['RES_pagetitle'];
	
	// Проеверяем, не добавлен ли этот ресурс уже в систему (просто оп имени)
    if(in_array($v['RES_pagetitle'], $alredy_imp)){
        continue;
    }
	
	// Добавляем только 15 рексурсов
    $count++;
    if($count > 15){
        break;
    }
	
	// Формируем соответствие полей - тут все индивидуально и надо править.
	
    if(in_array($v['RES_pagetitle'], $names)){
        $data['published'] = 0;
    }else{
        $data['published'] = 1;
    }
    $data['parent'] = $parent_id;
    $data['template'] = $template_id;
    $data['show_in_tree'] = '1';
    $data['content'] = $v['RES_content'];
    $data['description'] = $v['RES_category']." - ".$v['RES_subcategory'];
    
    
    //Данные
    
    if(!empty($v['TV_price'])){$data['price'] = $v['TV_price'];}
    if(!empty($v['TV_price_1'])){$data['price1'] = $v['TV_price_1'];}
    if(!empty($v['TV_price_10'])){$data['price10'] = $v['TV_price_10'];}
    if(!empty($v['TV_price_100'])){$data['price100'] = $v['TV_price_100'];}
    if(!empty($v['TV_price_5'])){$data['price5'] = $v['TV_price_5'];}
    if(!empty($v['TV_price_50'])){$data['price50'] = $v['TV_price_50'];}
    if(!empty($v['TV_price_500'])){$data['price500'] = $v['TV_price_500'];}

    if(!empty($v['TV_mark'])){
        $TV_mark = explode("||", $v['TV_mark']);
        foreach($TV_mark as $v1){
            switch($v1){
                case 2:
                    $data['new'] = 1;
                    break;
                case 3:
                    $data['popular'] = 1;
                    break;
            }
        }
    }
	/*
	*** Эта область из другого импорта, но примеры значения полей могут быть полезны:
	
	if($v['page_tags'] === 'хит' || $v['yml_param_recomend'] === "есть"){
	    $data['popular'] = 1;
	}
	if($v['page_tags'] === 'распродажа'){
	    $data['favorite'] = 1;
	}
	if($v['page_tags'] === 'новинка'){
	    $data['new'] = 1;
	}
	$data['vendor'] = $v['local_manuf_id'];
    
    //стандартные опции товара
	if(!empty($v['yml_param_color'])){
	    $data['color'] = $v['yml_param_color'];
	}
	$data['size'] = '';
	$data['tags'] = '';
    
	свои опции созданные в настройках MiniShop2

	if(!empty($v['yml_param_less70'])){
	    $data['options-cups'] = "до 70";
	}
	if(!empty($v['yml_param_more70'])){
	    $data['options-cups'] = "от 70";
	}
	if(!empty($v['yml_param_capuchinator'])){
	    $data['options-capuchinator'] = $v['yml_param_capuchinator'];
	}
	if((int)$v['exist_topvar'] === 0){
	    $data['options-exist'] = "Нет в наличии";
	}
	*/

    
    //TV
    if(!empty($v['TV_specification'])){$data['tv3'] = $v['TV_specification'];} // 3 в "tv3" это id TV
    if(!empty($v['TV_key'])){$data['tv1'] = $v['TV_key'];}
    if(!empty($v['TV_desc'])){$data['tv2'] = $v['TV_desc'];}
    
	// Формирование массива с фотографиями
    $product_images = array();
    if(!empty($v['TV_main_img'])){
        $imgName = $v['TV_main_img'];
        if(strpos($imgName,"items/") === false){
            $imgName = "items/".$imgName;
        }
        $product_images[] = "userimg/".$imgName;
    }
    if(!empty($v['TV_other_img'])){
        $TV_other_img = json_decode($v['TV_other_img'], true);
        foreach($TV_other_img as $k => $v){
            $imgName = $v['images'];
            if(strpos($imgName,"items/") === false){
                $imgName = "items/".$imgName;
            }
            $product_images[] = "userimg/".$imgName;
        }
    }
    //print_r($data);
    //print_r($product_images);
    //continue;
	
	// Запуск создания ресурса
    $response = $modx->runProcessor('resource/create', $data);
    
    /////////////////////////////////////////
    
    if ($response->isError()) {
        $hadErrors = true;
        echo __LINE__."\r\n";
        echo "<pre>".print_r($response->getResponse(), true)."</pre>";
        $id = false;
    }else{
        $id = $response->response['object']['id']; //id товара
        echo $id."
\r\n"; } if(count($product_images) && $id){ // Если все Окей - добавляем картинки foreach($product_images as $img){ $imgPath = MODX_BASE_PATH.$img; // Проверям - существует ли файл if(!is_file($imgPath)) { echo "файл ".$img." не найден"; continue; } // Особая магия загрузки картинок по API в галерею MiniShop2 $gallery = array( 'id' => $id, 'name' => basename($imgPath), 'file' => $imgPath ); $upload = $modx->runProcessor('gallery/upload', $gallery, array( 'processors_path' => MODX_CORE_PATH.'components/minishop2/processors/mgr/' )); if ($upload->isError()) { $hadErrors = true; echo __LINE__."\r\n"; echo $imgPath."\r\n"; echo "<pre>".print_r($upload->getResponse(), true)."</pre>"; } } } } if(!$hadErrors){ echo "<script>location.reload();</script>"; // Так как операция рексурсоемкая, делаем автоматизацию на JS - если нет ошибок, перезагружаем страницу }
Скрыть

Комментарии (1)

  1. User 17 июля 2022, 20:11 # 0
    Подскажите, а как можно импортировать поля самого минишопа? С тв спасибо, все понятно, а вот с полями магазина как быть?
    *Комментарий будет опубликован после проверки модератором

    Похожие статьи

    Генератор настроек MIGX

    Документация на русском по MODX MIGX

    Подсказки по работе и заготовки для MiniShop2

    pdoPage и getImageList - Постраничная навигация MIGX

    Импорт и экспорт в MiniShop2. Реализация 1

    Как включить HTTPS (SSL) в MODX - Подробная инструкция

    Генерация YML для выгрузки в маркет

    Примеры работы с API MODX

    Примеры выборки where, optionFilters, innerJoin

    pThumb - ресайз изображений. Примеры использования.

    Расширение свойств товаров minishop2

    Примеры использования

    Сайт на обслуживании (выключить сайт)

    Добавить в письмо контактную информацию

    Вывести getImageList только если он не пустой

    Тип поля "Список ресурсов" (resourcelist) с ограничением по родителю (parents)

    Оформление и настройка easyComm. Комментарии и отзывы на сайте.

    Поиск на сайте с пакетом SimpleSearch

    Простая и симпатичная галерея fancybox

    Подсчет и вывод количества потомков ресурса в MODX

    Галерея. Вывести обложки альбомов и фотографии

    Вывод tv-параметров в формате -

    Отредактировать письмо о заказе - добавить ТВ поле, или что-то еще

    Quip для MODX. Более рабочий вариант

    pdoResources Заготовки для работы

    Сниппет для вывода размера и расширения файла

    Простой аудио-плеер HTML5

    Вывести список всех опций MiniShop2

    Слайдер Slick slider в контенте ресурса

    Как контролировать кэш CSS и скриптов

    Изменить цену на товар в зависимости от количества при добавлении в корзину minishop2

    Подключить MODX в стороннем PHP файле

    Простейшая авторизация

    Как создать ресурс процессором $modx->runProcessor('resource/create', $props)

    Красивое адаптивное меню под pdoMenu

    Массово обновить ТВ, или другое поле через базу

    Создать свою страницу в админке

    Изменить формат номера заказа

    Сообщение о том, что сайт использует Cookie

    Получить grandparent. Вывести родитель родителя

    Симпатичный список файлов, загружаемых к ресурсу через MIGX

    Установить шаблон по-умолчанию для новых, создаваемых ресурсов

    Создать источник файлов

    Вывести все доступные плейсхолдеры

    Отредактировать шаблон письма

    Добавить скрипт перед тегом body

    Общая сумма по каждому товару в корзине Minishop2

    Создать раздел с паролем на сайте MODX

    Что делать если ее приходит почта администратору

    Фильтрация по TV параметрам в msProducts

    Дата на русском

    FontAwesome - часто используемые иконки для шаблонов MODX

    Создать пакет с пользовательской таблицей

    Заготовки для работы

    Курсы валют с cbr.ru на PHP

    Загрузка сниппета после загрузки страницы через AjaxSnippet

    getResources заготовки

    Обязательный чекбокс при оформлении заказа

    Обработка остатков заказа в miniShop2

    Соответствие названия классов с названиями таблиц в MySQL

    Разбить вывод pdoResources на несколько колонок (блоков)

    Баннеры с использованием BannerY

    Обновить alias (псевдоним) у всех ресурсов

    CSS для постраничной навигации pdoPage

    Вывести время загрузки (формирования) страницы

    Расширить таблицу site_content (объект modResource) за 5 минут

    Вырезать кавычки — фильтр-сниппет MODX

    Счетчик посещений и скачиваний для сортировки ресурсов

    Бесплатная доставка от 5000 рублей в MiniShop2

    Динамическое поле emailSubject в FormIt

    Скрыть информацию о том, что сайт работает на MODX

    Отсортировать ресурсы по количеству комментариев Quip MODx

    Изменить цену на товар, если в корзине лежит товар из особой категории minishop2

    Создать редирект через autoRedirector API

    Ответ для сервиса moneta.ru

    Вывести 404 ошибку по настройке TV MODX

    Cортировать по списку id в pdoResources и pdoTools

    Email сделать не обязательным полем

    Как разместить исходный код сниппета на сайте, в документации

    Ускорить установку MODX revo до пары кликов

    Постраничная навигация — набор параметров и CSS PdoPage

    Сделать все элементы статичными для Git и IDE

    Не работает подгрузка товаров ajax mfilter2 на мобильном

    Сделать поле размер обязательным

    Подключить текстовой редактор к доп. полям ресурса

    Настройка стилей для комментариев Tickets

    Кастомный чанк для AdminPanel

    Динамическая замена шаблона ресурса - плагин

    Разместить корзину внутри блока с оформлением заказа

    Плагин для формирования замороженных URL с редиректом

    xPDO Выборка из одной таблицы с зацепкой значения из другой

    Приветственный экран / заглушка на сайт

    Вложенные условия в xPDO MODX

    Вывести список всех родителей в ТВ поле ресурса

    Как получить данные пользователя сразу после авторизации через API

    Вывести список всех емэйлов miniShop2

    Если getParentIds не работает в плагине

    Контролировать кэширование файлов CSS и JS MiniShop2

    Не приходят / не отправляются письма - в чем причина?

    Кэширование в MODX: использование $modx->cacheManager

    Наш сайт использует куки, нажмите «ОК» если вы не против
    OK