[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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    getResources заготовки

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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