Лучший подход к обновлению продуктов и вариантов WooCommerce

Я относительно новичок в PHP, WordPress и WooCommerce. Но у меня есть 5-летний опыт работы с Oracle (SQL и PL/SQL), а также я много писал на JavaScript и немного на TypeScript.

Я работаю на своего клиента. У него есть интернет-магазин на базе WooCommerce. Мне нужно обновить stock_quantity, backorders и stock_status для продуктов и вариантов продуктов в соответствии с данными, поступающими с другого HTTP-сервера. В настоящее время у меня есть рабочее решение в TS/JS, которое работает на сервере Linode и в основном извлекает и объединяет/подготавливает данные для обновления WooCommerce. Но поскольку он использует WooCommerce HTTP API , который имеет ограничения на пакетное обновление (100 в секунду, все варианты должны обновляться для каждого родительского идентификатора также 1 раз в секунду), и я обновляю около 2500 продуктов и вариантов продуктов, это занимает очень долго для завершения процесса (~ 10 мин).

Процесс по шагам:

  1. Получить запас от стороннего API, это список SKU и их количество на складе.
  2. Получить все продукты для унитаза и варианты продуктов для унитаза
  3. Совпадение номенклатуры товаров WC и списков вариантов продукции по SKU.
  4. Обновление продуктов партиями по 100 штук в секунду (/products/batch)
  5. Обновление вариантов продукта для каждого родительского продукта в секунду (/products/${id}/variations/batch)

Я думаю, что есть лучший подход, о котором я думал:

  • Процедура PHP, ближе к БД, может быть, нет ограничений на пакетные обновления? Но я не могу найти какой-либо PHP API WooCommerce, кроме https://github.com/woocommerce/wc-api-php, который является оболочкой для HTTP API, поэтому, в конце концов, вернет тот же результат. .
  • Процедура базы данных MySQL в БД должна выполняться быстрее. Трудно проанализировать, какие таблицы нужно обновить, какими именно значениями. Может ли БД MySQL выполнять HTTP-запросы?

Какой подход лучше всего подходит для производительности, безопасности и учета обновлений PHP, WordPress и WooCommerce?

Очень интересная проблема. 10 минут кажутся слишком длинными. Можете ли вы описать свой процесс? Вы сначала тянете список продуктов? Что именно вы обновляете? Знаете ли вы, какие конечные точки API WooCommerce вы вызываете? Всегда можно написать какой-нибудь скрипт, который будет обновлять информацию непосредственно в базе данных, но тогда вы не будете запускать различные хуки, которые срабатывают. Например, отправка электронной почты клиенту. Возможно, ваше обновление вызывает некоторые электронные письма, которые затем вызывают задержку.

Ivo Jerkovic 21.12.2022 19:39

@IvoJerkovic спасибо, я добавил шаги программы.

HotFix 29.12.2022 01:51

Спасибо. У меня есть несколько идей сейчас. Вы можете удалить сервер JS Linode и вызвать сторонний API непосредственно с сервера woocommerce в php-скрипте. Затем вы можете обновлять продукты без API, используя php-код, который @VegasGeek предложил в своем ответе. Если вам нужно сохранить JS-сервер, вы можете сравнить количество и обновить только те товары, количество которых изменилось. Это должно сократить количество обновлений и ускорить процесс.

Ivo Jerkovic 29.12.2022 08:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
3
108
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Использование WC API для этого, безусловно, является наиболее «надежным» способом достижения вашей цели. API очень стабилен и (обычно) не ломается при изменении внутренних компонентов. Однако, как вы заметили, это самый медленный метод.

Ваш следующий лучший вариант — запустить обновление с использованием методов Woocommerce CRUD, но, опять же, не супер быстро, но быстрее, чем с использованием API.

$product = wc_get_product( $product_id );
$product->set_stock = 100;
$product->set_stock_status = 'instock';
$product->save();

Обновление базы данных напрямую, безусловно, самый быстрый способ, но подверженный ошибкам, потому что, например, в то время как состояние акций находится в wp_postmeta, это ТАКЖЕ таксономия, и оба должны совпадать, иначе у вас будут непредвиденные последствия.

Согласен с вами, я бы тоже пользовался остальным апи и следил за сервером. Возможно, простое увеличение ресурсов сервера может достаточно ускорить процесс.

Ivo Jerkovic 22.12.2022 19:49

Основываясь на дополнительных комментариях @HotFix и ответе, предоставленном @VegasGeek, я создал файл PHP, который можно запустить на сервере WordPress из командной строки или задания cron.

Идея:

  • Мы создадим PHP-скрипт, который загрузит WordPress внутрь, вызовет внешний API и при необходимости обновит количество товаров.

Предположим, что сторонний внешний API возвращает такой ответ JSON.

{
  "products": [
    {
      "id": 123,
      "sku": "PR1234",
      "name": "Product 1",
      "stock_quantity": 10
    },
    {
      "id": 456,
      "sku": "PR-3333",
      "name": "Product 2",
      "stock_quantity": 5
    }
  ]
}

Там 2 товара с артикулом и информацией о количестве.

PHP-скрипт требует wp-load.php, поэтому замените мой путь на свой. Для простоты я создал этот файл в корне веб-сайта, чтобы я мог запустить его и в браузере, но вы можете поместить его в другое место и изменить путь. Важно только, чтобы путь к wp-load.php был правильным. Эта строка кода загрузит WordPress и все плагины и сделает их доступными для скрипта.

Я имитирую ответ API с помощью простого статического файла JSON, вы заменяете конечную точку URL-адресом реального API. Кроме того, вам может понадобиться добавить некоторую аутентификацию для доступа к внешнему API, и ваши данные, вероятно, будут отличаться от моего примера, поэтому вам придется немного изменить код. Мы используем curl для получения данных из API, поэтому модифицировать вызов должно быть легко.

Затем мы перебираем продукты, находим продукт в WooCommerce по артикулу, проверяем, изменилось ли количество, и при необходимости обновляем.


// Load WordPress
define( 'WP_USE_THEMES', false );
//require_once( 'path/to/wp-load.php' );
require_once "wp-load.php";
// Set the API endpoint
//$api_endpoint = 'https://your-api.com/products';
$api_endpoint = 'http://bytwoo.local/TestData.json';

echo "<pre>";

// Build the cURL request to retrieve the list of products from the external API
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $api_endpoint );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );

// Execute the API request and decode the response
$response = json_decode( curl_exec( $ch ), true );
curl_close( $ch );

// Check if the API request was successful and if the products were found
if ( isset( $response['products'] ) && is_array( $response['products'] ) ) {
    // The products were found, loop through the products
    foreach ( $response['products'] as $product ) {
        // Get the product SKU and stock quantity
        $product_sku    = $product['sku'];
        $stock_quantity = $product['stock_quantity'];

        // Get the product ID from the SKU
        $product_id = wc_get_product_id_by_sku($product_sku);
        // Get the WooCommerce product object
        $wc_product =  wc_get_product($product_id);

        // Check if the product exists in the WooCommerce shop
        if ( ! empty( $wc_product ) ) {
            // The product exists, get the current stock quantity
            $current_stock_quantity = $wc_product->get_stock_quantity();

            // Check if the stock quantity needs to be updated
            if ( $stock_quantity != $current_stock_quantity ) {
                // Set the new stock quantity and stock status
                $wc_product->set_stock_quantity($stock_quantity);
                $wc_product->set_stock_status( 'instock' );

                // Save the product
                $wc_product->save();

                echo PHP_EOL."Successfully updated stock quantity for product with SKU '$product_sku' to $stock_quantity";
            } else {
                echo PHP_EOL."Stock quantity for product with SKU '$product_sku' is already up to date";
            }
        } else {
            echo PHP_EOL."Product with SKU '$product_sku' not found in WooCommerce shop";
        }
    }
} else {
    echo PHP_EOL."No products found in external API";
}

echo "</pre>";

Я протестировал его с двумя продуктами, только один из них нуждался в обновлении. Результат (лог):

Stock quantity for product with SKU 'PR1234' is already up to date
Successfully updated stock quantity for product with SKU 'PR-3333' to 5

Другие вопросы по теме