В процессе администрирования интернет-магазина часто возникает задача импорта, экспорта товаров. Рассмотрим инструменты которые помогут реализовать этот процесс.
Про выгрузку товаров в формате YML сделал отдельный пост.
Экспорт товаров WC
Предположим, что на одном из сайтов у нас есть товары, которые надо перенести (скопировать) на другой сайт. Либо надо сделать выгрузку товаров для массового редактирования. Используем плагин WP All Export.
Выборка товаров для экспорта доступна только в Premium версии.
Импорт товаров WC
Для импорта записей из различных форматов (xml, csv) существует отличный плагин WP All Import. Для более детального импорта товаров в Woocommerce к плагину WP All Import есть специальное дополнение WP All Import — WooCommerce Add-On.
Допускается импорт файлов в форматах csv и xml. Загружаем файл, назначаем полям загруженного файла поля товара.
Эксперимент 1: загрузка 536897 шт товаров (всего 3 поля: название, артикул, цена). Загружаю форматом CSV. Начало загрузки 23:17. За 30 минут 6000 записей. 1 час — 3%, 12000 записей. импорт остановлен.
Появилась необходимость удаления загруженных товаров (12000). Сделать это можно плагином Bulk Delete (50 000). Есть вариант удалить все товары через SQL-запрос, но сам еще не пробовал:
DELETE FROM wp_term_relationships WHERE object_id IN (SELECT ID FROM wp_posts WHERE post_type = 'product');
DELETE FROM wp_postmeta WHERE post_id IN (SELECT ID FROM wp_posts WHERE post_type = 'product');
DELETE FROM wp_posts WHERE post_type = 'product';
Удалить все таксономии Woocommerce:
DELETE relations.*, taxes.*, terms.*
FROM wp_term_relationships AS relations
INNER JOIN wp_term_taxonomy AS taxes
ON relations.term_taxonomy_id=taxes.term_taxonomy_id
INNER JOIN wp_terms AS terms
ON taxes.term_id=terms.term_id
WHERE object_id IN (SELECT ID FROM wp_posts WHERE post_type='product')
Эксперимент 2: тот же файл, но загружаю файлом xml (размер файла 14.53 Mb). Включил настройку Enable Stream Reader, которая должна ускорить импорт. А также включил функцию Increase speed by disabling do_action calls in wp_insert_post during import, для того чтобы отключить функцию do_action во время импорта.
Необходимо при парсинге с xml выбирать вариант row. Возникает проблема: при переходе на шаг Определение уникального ключа, парсинг скидывается со строки (row) на data — надо за этим следить.
За 5 мин. 1450 записей. Остановил импорт, т.к. обнаружил, что в процессе создания xml файла почему то из 536897 строк осталось лишь 65536 шт. Скорость загрузки в целом удовлетворительна. Но необходимо научиться правильно конвертировать xls в xml.
Попался некий метод импорта. Уверяют, что 120000 записей импортируются менее чем за 20 мин.:
<?php
// Load WordPress
require_once 'wp-load.php';
require_once ABSPATH . '/wp-admin/includes/taxonomy.php';
date_default_timezone_set('Europe/Moscow');
$time_start = microtime(true);
$cache = true;
if ($cache) {
wp_defer_term_counting(true);
wp_defer_comment_counting(true);
wp_suspend_cache_addition(true);
// Create post
for ($i = 0; $i < 100000; $i++) {
$term = wp_insert_term('product category-' . mt_rand(1, 50), 'product_cat');
if (is_wp_error($term)) {
$term_id = $term->error_data['term_exists'] ?? null;
} else {
$term_id = $term['term_id'];
}
$post_id = wp_insert_post(array(
'post_title' => 'Sample post -' . $i,
'post_content' => 'Post content - ' . $i,
'post_date' => date('Y-m-d H:i:s'),
'post_author' => 1,
'post_type' => 'product',
'post_status' => 'publish',
));
wp_set_object_terms($post_id, $term_id, 'product_cat');
update_post_meta($post_id, '_visibility', 'visible');
update_post_meta($post_id, '_stock_status', 'instock');
update_post_meta($post_id, 'total_sales', '0');
update_post_meta($post_id, '_downloadable', 'no');
update_post_meta($post_id, '_virtual', 'no');
update_post_meta($post_id, '_regular_price', mt_rand(100, 1000));
update_post_meta($post_id, '_sale_price', '');
update_post_meta($post_id, '_purchase_note', '');
update_post_meta($post_id, '_featured', 'no');
update_post_meta($post_id, '_weight', '');
update_post_meta($post_id, '_length', '');
update_post_meta($post_id, '_width', '');
update_post_meta($post_id, '_height', '');
update_post_meta($post_id, '_sku', 'SKU-' . $post_id . '-' . mt_rand(1000, 10000));
update_post_meta($post_id, '_product_attributes', array());
update_post_meta($post_id, '_sale_price_dates_from', '');
update_post_meta($post_id, '_sale_price_dates_to', '');
update_post_meta($post_id, '_price', mt_rand(100, 1000));
update_post_meta($post_id, '_sold_individually', '');
update_post_meta($post_id, '_manage_stock', 'yes');
update_post_meta($post_id, '_backorders', 'no');
update_post_meta($post_id, '_stock', mt_rand(1, 10));
}
if ($cache) {
wp_defer_term_counting(false);
wp_defer_comment_counting(false);
wp_suspend_cache_addition(); // включаем кэширование
}
$time_end = microtime(true);
$execution_time = ($time_end - $time_start);
echo 'Total Execution Time: ' . $execution_time . ' Seconds' . PHP_EOL;
Пока не знаю как к этому относится — надо пробовать.
Процедура импорта товаров
Для импорта нужен файл с таблицей данных в формате CSV. Файл CSV можно либо создать из таблицы, либо создать экспортом с другого сайта, либо спарсить с любого сайта.
1. Создаем новый импорт и указываем путь к CSV файлу. Выбираем из списка какой тип записи будем добавлять.
2. Второй шаг: здесь должны отобразится поля таблицы в нормальном человеческом виде. Если вместо букв символы — надо проверить кодировку (создать в Notepad++ новый файл (по умолчанию utf-8 без bom), скопировать в него содержимое svg и сохранить).
3. Третий шаг: расставляем поля таблицы в поля записи.
Изображения
Источник изображений:
- Внешние изображения
- Изображения из Медиабиблиотеки
- Изображения из определенной директории сайта
Настройки импорта изображений:
- Поиск по библиотеке мультимедиа для существующих изображений перед импортом новых изображений
- Сохранять изображения в настоящее время в мультимедиа
- Установите первое изображение в виде Миниатюры (_thumbnail_id)
- Если изображения не загружаются успешно, создать запись в качестве Черновика.
4. В 4 шаге указываем уникальный идентификатор: артикул, либо ID.
Импорт атрибутов
При импорте атрибутов важно:
- знать slug импортируемого атрибута и вводить его без pa_ вручную в поле Name
- в поле Values подставляем переменную со значением атрибута
- должны быть включены чекбоксы Is Visible, Is Taxonomy и
Auto-Create Terms

Если значение атрибута при импорте будем пустым, то атрибут товару не будет назначен. т.е. если есть товары разной направленности с разным набором атрибутов, то можно дня них создавать общий шаблон загрузки.
Если атрибут удален (или какое-либо значение атрибута), то из товаров этот атрибут удалится при обновлении товара.
Обновление товаров через экспорт импорт
Если сайт не синхронизирован с 1С, а товары нужно массово обновить, можно сделать экспорт, внести правки и закачать обратно на сайт. Разбираемся, как все это, безопасно для записей, проделать.
Ключевым полем в данном мероприятии будет ID записи, т.к. он уникален, в отличие от многих других полей.
Бесплатная версия предлагает экспорт только в CSV — это не проблема, можно воспользоваться онлайн конвертером, например convertio.co. А при импорте (если редактировали файл в excele) наоборот конвертируем в csv.
Первая проблема с которой столкнулся — вариации. Плагин выгружает и вариации целиком и каждую вариации по отдельности. Чтобы этого избежать, при формировании полей импорта, нужно открыть настройки Advanced Options и выбрать второй вариант Only export product variations (только вариации). !Но эта настройка не действует.
При импорте, на самом первом шаге выбираем Existing Items, тогда на финальном шаге у нас будет варианты выбора уникального поля, в том числе по post ID.

Если нам необходимо обновить только конкретные поля WC, то на четвертом шаге, в настройках When WP All Import finds new or changed data… выбираем Choose which data to update. И если не планируем, чтобы создавались новые записи (случайно) снимаем галку с Create new posts from records newly present in your file.

Все отлично! Товары обновляются, в том числе и вариации, т.к. у каждой вариации свой post ID.
Импорт только наличия
Чтобы импортировать наличие товара потребуется колонка с остатками. На основе остатков WC автоматически проставляет статус наличия: instock, outofstock или onbackorder.
Если импортировать только остатки и наличие, то в любом случае нужно обновлять 2 поля: _stock и _manage_stock. При этом если нужно чтобы товары которых нет в наличие были доступны под заказ выбираем опцию для всех товаров Backorder allow, тогда в списке изменяемых полей нужно добавить _backorders.
XML FEED
Данный фид нужен для экспорта товаров с периодическим обновлением, для торговых площадок и партнерских программ. Неплохой плагин для данного функционала — WooCommerce Product Feed (9000 установок). Полное название в репозитории: WooCommerce Product Feed : Google Shopping,Facebook Product Ad,Amazon,eBay and Many More — это из-за того что в плагине есть заготовленные настройки фида для популярных сервисов.
Работа с плагином
После активации на админ-панели появится пункт WooFeed. Создание фида заключается в том что мы создаем необходимые для выгрузки строки. Доступные форматы: XML, TXT, CSV. После этого нажимаем создать м сохранить фид (в бесплатной версии фид создается не более чем для 2000 товаров). После создания у фида появляется ссылка + возможность его обновления по определенной частоте.
Сделать у импортированных товаров статус «Предзаказ»
В шаге назначения полей, в группе настроек Woocommerce вкладка Inventory включаем следующие параметры:
Manage stock? Да
Stock Qty пишем «0»
Allow Backorders? Allow
Остальное не трогаем (Stock status Set automatically).
На предпоследнем шаге настраиваем обновление этих полей:

Импорт связанных товаров
При импорте сначала желательно загрузить все товары, а потом отдельным импортом загрузить эти поля (upsells и crosssells). При импорте поля не должны быть пустыми, и если значения заполнены не у всех товаров, то импорт делать по раздельности (отдельно upsells отдельно crosssells). Возможно, но это не точно, после разделяющей запятой, лучше добавлять пробел.
Как это сделать?
На каждом хостинге по разному. Самый простой способ: обратится с данным вопросом в тех. поддержку. Если самому — то надо искать модули PHP и там включать соответствующие модули.