Если вы делаете или уже работаете с интернет-магазином на WooCommerce, рано или поздно возникнет желание автоматизировать добавление и обновление товаров и цен. А если каталог товаров большой, то есть смысл с этого и начать. Ниже — мои наработки по добавлению товаров и категорий в WooCommerce по API с помощью скрипта. Думаю, эта статья на много облегчит вам жизнь, т.к. не придется собирать сведения «по крупицам», из разных источников.
Пока писал статью «Magento 2.1: Добавление категорий и товаров по API«, вспомнил, что где-то год назад решал аналогичную задачу для Woocommerce. А в WordPress с этим, как водится, все немного проще. Поэтому возникло желание поделится.
Не раз уже писал, и еще раз повторюсь: я не профессиональный программист. Поэтому вид и структура кода далеко не идеальны. Многое, наверняка, можно сделать значительно проще. Но данное решение работает корректно, поэтому можно пользоваться им для примера, и для изучения WordPress API.
Итак, сначала создаем файл php скрипта в корневой папке с wordpress. Можно и не в корневой, но подключение к API WordPress тогда будет с другим путем.
В файле, сначала подключаемся к API:
require_once( 'wp-load.php' );
require_once( ABSPATH . '/wp-admin/includes/taxonomy.php');
ini_set('display_errors', 'On'); // сообщения с ошибками будут показываться
error_reporting(E_ALL); // E_ALL - отображаем ВСЕ ошибки
set_time_limit(0); //Не ограничиваем время работы скрипта
Если нужно, после этого качаем файл с XML поставщика и парсим его в массив. Этот процесс тут я описывать не буду, в общем то, это стандартный процесс в PHP, и отношения к WordPress не имеет.
Добавление категорий товаров WooCommerce по API
Далее — добавляем категории. Для этого нужно сформировать массив данных добавляемой категории и воспользоваться функцией WooCommerce wp_insert_category. $xmlCat — массив с описанием категорий сформированный из XML поставщика.
Но сначала проверяем, существует ли такая категория или нет. Потом ищем ID родительской категории, что бы создать нужную структуру каталога.
В общем то, по коду много комментариев, поэтому излишне тут описывать не буду.
//СТАРТ БЛОКА ДОБАВЛЕНИЯ КАТЕГОРИЙ
$xmlCat = $xml -> categories -> category;
$count = count($xmlCat);
$key = 0;
while ($count >= $key) {
$CatName = (string)$xmlCat[$key];
$ParentID = (string)$xmlCat[$key]['parentId'];
$CatID = (string)$xmlCat[$key]['id'];
$k = SearchCat($CatName);
$ParentCatID = '';
if (!$k) {
//Если такая категория еще не создана проверяем, есть ли у нее $ParentID,
//ищем ид родительской категории в WordPress и добавляем новую категорию
if ( $ParentID ) {
$x = SearchParentId ($ParentID, $xmlCat);
if ($x) { $x = SearchCat($x); };
if ($x) {
$ParentCatID = (array)$x -> term_id;
$ParentCatID = (string)$ParentCatID[0];
}
};
//Найти категорию по названию. Родительскую категорию. Обновить в скрипте (не ИД ХМЛ, а ИД Вордпресса)
$cat_defaults = array(
//'cat_ID' => $CatID, // ID категории, которую нужно обновить. 0 - добавит новую категорию.
'cat_name' => $CatName, // название категории. Обязательный.
'category_description' => '', // описание категории
'category_nicename' => '', // слаг категории
'category_parent' => $ParentCatID, // ID родительской категории
'taxonomy' => 'product_cat' // таксономия. Измените, чтобы добавить элемент другой таксономии. Например для меток будет post_tag
);
//print_r ($cat_defaults );
//О функции добавления категорий, устнарение ошибки Call to undefined function wp_insert_category()
//http://wp-kama.ru/function/wp_insert_category
$cat_id = wp_insert_category( $cat_defaults, true);
//print_r ($cat_id);
} else {/*echo 'Категория ID ' ,$k -> term_id,' существует' */;};
$key++;
};
Function SearchCat ($Cat) {
//Функция ищет категорию по названию. Возвращает WordPress id категории, если найдена и false, если нет
$cat_id = get_term_by( 'name', $Cat, 'product_cat', 'OBJECT', 'raw' );
//print_r ($cat_id);
if ($cat_id) {return $cat_id;} else {return false;};
}
Function SearchParentId ($ParentID, $xmlCat) {
//Функция ищет название категории по ParentID
$size = sizeof( $xmlCat ) - 1;
$i = 0;
while($i <= $size) {
$CatID = (string)$xmlCat[$i]['id'] ;
if (isset( $xmlCat[$i] ) ){
if ($CatID == $ParentID) {
return (string)$xmlCat[$i];
}
} else {return False;};
$i++;
}
}
//КОНЕЦ БЛОКА ДОБАВЛЕНИЯ КАТЕГОРИЙ
Добавление товаров в WooCommerce по API
Перед добавлением товара, так же нужно проверить, существует ли уже такой товар (по артикулу). У меня для этого используется цикл, который вызывает такие функции:
//СТАРТ БЛОКА ДОБАВЛЕНИЯ ТОВАРОВ
$xmlOffers = $xml -> offers -> offer;
foreach ($xmlOffers as $k => $v) {
//Проверяем, есть ли уже товар с таким артикулом
$Find = FindArt($v);
if (!$Find){
Xml2Perem($v);} //Если нет - добавляем
else {
echo $Find;
};
};
Function FindArt ($xmlOffer){
//Функция проверяет, есть ли товар с таким артикулом. Если есть - выводит кол-во товаров с таким артикулом.
//Если нет - возвращает False
$Art = (string)$xmlOffer["id"];
$NumArt = SearchArt ($Art);
if ($NumArt) {
$massage = 'Найдено '.$NumArt. 'позиций с артикулом '.$Art ;
return $massage;
} else {
return false;
};
};
Function SearchArt ($Art ) {
//Функция ищет товар с заданным артикулом. Если находит - возвращает кол-во найденых товаров с таким артикулом (число)
// Пример получения товаров по фильтру
//http://woocommerce-russian.ru/vyvodim-tovary-v-woocommerce-po-tegam/
//Описание WP_Query
//http://wp-kama.ru/function/wp_query#znakomstvo-s-wp_query
//Работа с произвольными полями WP_Query
//https://wpmag.ru/2014/rabota-s-proizvolnyimi-polyami-v-wp_query/
$args = array(
'post_type' => 'product',
'meta_query' => array(
array(
'key' => '_SKU',
'value' => $Art,
),),
) ;
$query = new WP_Query( $args );
//$query = $query -> posts;
//Получаем количество товаров соответствующих результатам поиска
$product_count = $query -> post_count;
//print_r($product_count ); //print_r ($query);
wp_reset_postdata();
return $product_count ;
}
Function Xml2Perem ($xmlOffer) {
//Получает массив одного товара. Раскладывает его на переменные - свойства
//И передает в функцию StartAdd для добавления товара на сайт
$OpisProd = (string)($xmlOffer -> description);
$KratOpisProd = (string)($xmlOffer -> namefull);
$NameProd = (string)($xmlOffer -> name);
$ProdCat = (string)($xmlOffer -> subcategory);
if ($xmlOffer["available"] == 'true') {$Stock = 'instock';} else {$Stock = 'outofstock';};
$BasePrice = (string)($xmlOffer -> price1);
$SalePrice = ''; //price2 в XML это не цена со скидкой, а отпускная цена для опта
$Note = '';
$Weight = (string)($xmlOffer -> weight);
$Length = '';
$Width = '';
$Height = '';
$Art = (string)$xmlOffer["id"];
//Проверяем некоторые значения, что бы были не нулевыми. Если 0 - стираем.
if ((string)($xmlOffer -> demission) <= 0) {$Razmer = "";} else { $Razmer = (string)($xmlOffer -> demission); };
if ((string)($xmlOffer -> gabarit) <= 0) {$gabarit = "";} else { $gabarit = (string)($xmlOffer -> gabarit); };
if ((string)($xmlOffer -> weight) <= 0) {$weight = "";} else { $weight = (string)($xmlOffer -> weight); };
if ((string)($xmlOffer -> nettoweight) <= 0) {$nettoweight= "";} else { $nettoweight = (string)($xmlOffer -> nettoweight); };
if ((string)($xmlOffer -> garantee) <= 0) {$garantee = "";} else { $garantee = (string)($xmlOffer -> garantee); };
if ((string)($xmlOffer -> nettoweight) <= 0) {$nettoweight= "";} else { $nettoweight = (string)($xmlOffer -> nettoweight); };
//Пример массива добавления атрибутов
//http://wordpress.stackexchange.com/questions/134026/setting-an-attribute-as-variation-in-woo-commerce-via-php
$TaxAttributes = array (
'vendor'=> (string)($xmlOffer -> vendor),
'country'=> (string)($xmlOffer -> country),
);
$Attributes = array(
'vendorCode'=> array(
'name'=>'Артикул производителя',
'value'=>(string)($xmlOffer -> vendorCode),
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '0'
),
'code'=> array(
'name'=>'Код',
'value'=>(string)($xmlOffer -> code),
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '0'
),
'demission'=> array(
'name'=>'Размер, см',
'value'=>$Razmer,
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '0'
),
'gabarit'=> array(
'name'=>'Габариты упаковки, см',
'value'=>$gabarit,
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '0'
),
'weight'=> array(
'name'=>'Вес, кг',
'value'=>$weight,
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '0'
),
'nettoweight'=> array(
'name'=>'Вес нетто, кг',
'value'=>$nettoweight,
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '0'
),
'garantee'=> array(
'name'=>'Гарантия, мес',
'value'=>$garantee,
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '0'
),
'stockstatus'=> array(
'name'=>'Остаток',
'value'=>(string)($xmlOffer -> stockstatus),
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '0'
) );
$thumb_url = (string)($xmlOffer -> picture[0]);
$thumb_url_all = (array)($xmlOffer -> picture);
unset($thumb_url_all[0]);
AddProduct($OpisProd, $KratOpisProd, $NameProd, $ProdCat, $Stock, $BasePrice, $SalePrice, $Note, $Weight, $Length, $Width, $Height, $Art, $Attributes, $TaxAttributes, $thumb_url, $thumb_url_all);
};
Сама функция добавления товара в WooCommerce выглядит так.
Как видно, в функции используются отдельные блоки для добавления превью, доп картинок. Показан механизм добавления свойств товаров.
Что касается свойств, для работы скрипта нужно вручную создать атрибуты Страна, Производитель, Цвет, Материал и т.д. в Woocommerce и прописать их идентификаторы в скрипте. Например, pa_proizvoditel (ид атрибута Производитель). Добавление производится только по заданному, конечному количеству атрибутов.
Так же, из кода можно видеть, каким образом добавляются теги к товару.
Код специально не чищу, что бы была видна механика работы.
Function AddProduct($OpisProd, $KratOpisProd, $NameProd, $ProdCat, $Stock, $BasePrice, $SalePrice, $Note, $Weight, $Length, $Width, $Height, $Art, $Attributes, $TaxAttributes, $thumb_url, $thumb_url_all) {
//Функция добавления нового товара (продукта) в WordPress WooCommerce
//Передать параметры:
//$OpisProd - описание товара
//$KratOpisProd - краткое описание
//$NameProd - название товара
//$ProdCat - категория товара
//$Stock - Статус остатка ('instock' - в наличии, 'outofstock' - не в наличии, 'onrequest' - по запросу)
//$BasePrice - базовая цена
//$SalePrice - цена распродажи
//$Note- Примечание к покупке (что бы отправить его клиенту после покупки)
//$Weight - Вес
//$Length - Длина
//$Width - Ширина
//$Height - Высота
//$Art - Артикул
//$Attributes() - доп.атрибуты (массив)
//$thumb_url - путь к превью, например: http://alexabak-wordpress.tw1.ru/wp-content/themes/boemia-free/images/logo.png
//$thumb_url_all() - массив с URL к доп картинкам
//--------------------------------------------Добавление товара--------------------------------------------------
wp_insert_post
$post = array(
'post_author' => 1,
'post_content' => $OpisProd, //Описание товара
'post_excerpt' => $KratOpisProd,
'post_status' => "publish",
'post_title' => $NameProd, // Название товара
// 'post_parent' => '123', //ID родительской записи
'post_type' => "product",
);
//Create post
$post_id = wp_insert_post($post);
// http://wordpress.stackexchange.com/questions/137501/how-to-add-product-in-woocommerce-with-php-code
wp_set_object_terms( $post_id, $ProdCat, 'product_cat' ); //Категория товара
wp_set_object_terms($post_id, 'simple', 'product_type'); //Тип товара (Простой товар)
update_post_meta( $post_id, '_visibility', 'visible' ); // Видимость: открыто
update_post_meta( $post_id, '_stock_status', $Stock); //Статус Остатка - в наличии
//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', $BasePrice); //Базовая цена
update_post_meta( $post_id, '_sale_price', $SalePrice); //Цена распродажи
update_post_meta( $post_id, '_purchase_note', $Note); //Примечание к покупке (что бы отправить его клиенту после покупки)
update_post_meta( $post_id, '_featured', "no" );
update_post_meta( $post_id, '_weight', $Weight); // Вес
update_post_meta( $post_id, '_length', $Length); // Длина
update_post_meta( $post_id, '_width', $Width ); // Ширина
update_post_meta( $post_id, '_height', $Height); // Высота
update_post_meta($post_id, '_sku', $Art); // Артикул
//update_post_meta( $post_id, 'short_description', 'short_description');
//update_post_meta( $post_id, '_sale_price_dates_from', "99" );
//update_post_meta( $post_id, '_sale_price_dates_to', "999" );
//update_post_meta( $post_id, '_sold_individually', "888" );
update_post_meta( $post_id, '_manage_stock', "no" );
//update_post_meta( $post_id, '_backorders', "no" );
//update_post_meta( $post_id, '_stock', "777" );
//Устанавливаем мета _price. Работает она странно. _price должна равнятся актуальной цене товара/
//Если _sale_price задан, но не совпадает с _price, для цены товара woocommerce берет _price.
//Поэтому, сначала проверяем.
if ($SalePrice<=0) {
update_post_meta( $post_id, '_price', $BasePrice ); //Цена
} else {
update_post_meta( $post_id, '_price', $SalePrice ); //Цена
};
//Привязываем товары к таксономиям (Назначение атрибутов товаров)
//Необходимо создать вручную таксономии Производитель pa_proizvoditel
//И Страна
wp_set_object_terms($post_id, $TaxAttributes['country'], 'pa_strana');
$thedata = Array(
'name'=>'pa_strana',
'value'=>$TaxAttributes['country'],
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '1'
);
$Attributes = array_merge (array( 'pa_strana' => $thedata), $Attributes);
wp_set_object_terms($post_id, $TaxAttributes['vendor'], 'pa_proizvoditel');
$thedata = Array(
'name'=>'pa_proizvoditel',
'value'=>$TaxAttributes['vendor'],
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '1'
);
$Attributes = array_merge (array( 'pa_proizvoditel'=> $thedata), $Attributes);
//Цвет
$taxColor = false;
if (stripos($NameProd, 'красный')) {$taxColor[] = 'Красный';};
if (stripos($NameProd, 'красная')) {$taxColor[] = 'Красный';};
if (stripos($NameProd, 'бежевый')) {$taxColor[] = 'Бежевый';};
if (stripos($NameProd, 'бежевая')) {$taxColor[] = 'Бежевый';};
if (stripos($NameProd, 'оранжевый')) {$taxColor[] = 'Оранжевый';};
if (stripos($NameProd, 'оранжевая')) {$taxColor[] = 'Оранжевый';};
if (stripos($NameProd, 'желтый')) {$taxColor[] = 'Желтый';};
if (stripos($NameProd, 'желтая')) {$taxColor[] = 'Желтый';};
if (stripos($NameProd, 'зеленый')) {$taxColor[] = 'Зеленый';};
if (stripos($NameProd, 'зеленая')) {$taxColor[] = 'Зеленый';};
if (stripos($NameProd, 'голубой')) {$taxColor[] = 'Голубой';};
if (stripos($NameProd, 'голубая')) {$taxColor[] = 'Голубой';};
if (stripos($NameProd, 'синий')) {$taxColor[] = 'Синий';};
if (stripos($NameProd, 'синяя')) {$taxColor[] = 'Синий';};
if (stripos($NameProd, 'фиолетовый')) {$taxColor[] = 'Фиолетовый';};
if (stripos($NameProd, 'фиолетовая')) {$taxColor[] = 'Фиолетовый';};
if (stripos($NameProd, 'белый')) {$taxColor[] = 'Белый';};
if (stripos($NameProd, 'белая')) {$taxColor[] = 'Белый';};
if (stripos($NameProd, 'серебряный')) {$taxColor[] = 'Серебряный';};
if (stripos($NameProd, 'серебряная')) {$taxColor[] = 'Серебряный';};
if (stripos($NameProd, 'розовый')) {$taxColor[] = 'Розовый';};
if (stripos($NameProd, 'розовая')) {$taxColor[] = 'Розовый';};
if (stripos($NameProd, 'серый')) {$taxColor[] = 'Серый';};
if (stripos($NameProd, 'серая')) {$taxColor[] = 'Серый';};
if (stripos($NameProd, 'цветной')) {$taxColor[] = 'Цветной';};
if (stripos($NameProd, 'цветная')) {$taxColor[] = 'Цветной';};
if (count($taxColor) > 0) {
if ((string)$taxColor[0] != '') {
wp_set_object_terms($post_id, (string)$taxColor[0], 'pa_tsvet');
$thedata = Array(
'name'=>'pa_tsvet',
'value'=>(string)$taxColor[0],
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '1'
);
$Attributes['pa_tsvet' ] = $thedata;
};
};
//МАТЕРИАЛЫ
//По ключевикам в названии товара
$taxMat = false;
if (stripos($NameProd, 'дерев')) {$taxMat[] = 'Дерево'; };
if (stripos($NameProd, 'металл')) {$taxMat[] = 'Металл'; };
//По ключевым словам из Описания Товара
if (stripos($OpisProd, 'пластик')) {$taxMat[] = 'Пластик';};
if (stripos($OpisProd, 'пластмасс')) {$taxMat[] = 'Пластмасса';};
if (stripos($OpisProd, 'натуральное дерево')) {$taxMat[] = 'Натуральное дерево';};
if (stripos($OpisProd, 'каучуковое дерево')) {$taxMat[] = 'Каучуковое дерево';};
if (stripos($OpisProd, 'фанер')) {$taxMat[] = 'Фанера';};
if (stripos($OpisProd, 'массив')) {$taxMat[] = 'Массив';};
if (stripos($OpisProd, 'МДФ')) {$taxMat[] = 'МДФ';};
if (stripos($OpisProd, 'ДСП')) {$taxMat[] = 'ДСП';};
if (stripos($OpisProd, 'дерево')) {$taxMat[] = 'Дерево';};
if (stripos($OpisProd, 'бук')) {$taxMat[] = 'Бук';};
if (stripos($OpisProd, 'сталь')) {$taxMat[] = 'Сталь';};
if (stripos($OpisProd, 'сосна')) {$taxMat[] = 'Сосна';};
if (stripos($OpisProd, 'текстиль')) {$taxMat[] = 'Текстиль';};
if (stripos($OpisProd, 'синтепон')) {$taxMat[] = 'Синтепон';};
if (stripos($OpisProd, 'хлопок')) {$taxMat[] = 'Хлопок';};
if (stripos($OpisProd, 'ткань')) {$taxMat[] = 'Ткань';};
if (stripos($OpisProd, 'винил')) {$taxMat[] = 'Винил';};
if (stripos($OpisProd, 'флок')) {$taxMat[] = 'Флок';};
if (stripos($OpisProd, 'картон')) {$taxMat[] = 'Картон';};
if (count($taxMat) > 0) {
if ((string)$taxMat[0] != ''){
wp_set_object_terms($post_id, (string)$taxMat[0], 'pa_material');
$thedata = Array(
'name'=>'pa_material',
'value'=>(string)$taxMat[0],
'is_visible' => '1',
'is_variation' => '0',
'is_taxonomy' => '1'
);
$Attributes['pa_material' ] = $thedata;
};
};
update_post_meta( $post_id, '_product_attributes', $Attributes);
//Добавление меток товаров
$tags = false;
// Установка тегов по цене "До ХХХ руб" -
if ($BasePrice <= 1000) {$tags[] = 'До 1000 рублей';}
elseif ($BasePrice > 1000 and $BasePrice < 3000) {$tags[] = 'До 3000 рублей';}
elseif ($BasePrice > 3000 and $BasePrice < 5000) {$tags[] = 'До 5000 рублей';}
elseif ($BasePrice > 5000 and $BasePrice < 7000) {$tags[] = 'До 7000 рублей';}
elseif ($BasePrice > 7000 and $BasePrice < 10000) {$tags[] = 'До 10000 рублей';};
//По стране
if ($TaxAttributes['country'] == 'США') {$taxMat[] = 'Сделано в Америке';}
elseif ($TaxAttributes['country'] == 'Германия'){$tags[] = 'Немецкое качество';}
elseif ($TaxAttributes['country'] == 'Россия'){$tags[] = 'Сделано в России';};
if ($tags) {
wp_set_object_terms( $post_id, $tags, 'product_tag'); //Устанавливаем созданные метки
};
//-----------------------------------------------------Добавление превью------------------------------------------------------------------------
//http://jafty.com/blog/programatically-create-woocommerce-products-with-variations/
//add product image:
//require_once 'inc/add_pic.php';
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . "wp-admin" . '/includes/image.php');
// Download file to temp location
$tmp = download_url( $thumb_url );
if( !is_wp_error( $tmp ) ) {
// Set variables for storage
// fix file name for query strings
preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $thumb_url, $matches);
$file_array['name'] = basename($matches[0]);
$file_array['tmp_name'] = $tmp;
//print_r ($file_array);
//use media_handle_sideload to upload img:
$thumbid = media_handle_sideload( $file_array, $post_id, $NameProd); //Описание изображения
set_post_thumbnail($post_id, $thumbid);
}
//----------------------------------------------------КонецДобавление превью------------------------------------------------------------------------
//----------------------------------------------------Добавление доп картинок------------------------------------------------------------------------
if (is_array($thumb_url_all)) {
foreach($thumb_url_all as $key => $value)
{
//print_r($tmp2);
$tmp2 = download_url( $value );
if ($tmp2) {
// fix file name for query strings
preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $value, $matches);
$file_array2['name'] = basename($matches[0]);
$file_array2['tmp_name'] = $tmp2;
$imgID[$key] = media_handle_sideload( $file_array2, $post_id, $NameProd); //Описание изображения
//print_r($imgID);
};
}
update_post_meta( $post_id, '_product_image_gallery', implode(", ", $imgID));
};
wp_update_post( $post_id);
shell_exec('rm -rf /tmp/*'); //Очищаем папку tmp что бы небыло переполнения
//--------------------------------------КонецДобавление доп картинок------------------------------------------------------------------------
echo ' Пост № - '; print_r ($post_id);
//print_r (get_post_meta( '339', '_price'));
}
Удачи с вашим магазином на WooCommerce!
