WooCommerce запрашивает все продукты - PullRequest
0 голосов
/ 31 января 2020

Существует сайт, на котором представлены товары из тысяч интернет-магазинов. Они получают товары всех этих интернет-магазинов через файл XML.

Я создал файл XML, в котором содержатся все мои продукты 2k +.

Для меня чтобы создать этот список продуктов XML, я сделал БОЛЬШОЙ запрос, в котором перечислен каждый отдельный продукт с его переменными и каждый вариант, который имеет переменная.

Весь запрос занимает около 30-40 секунд до окончания sh и сгенерировать мой XML файл.

Но иногда, когда сервер достаточно загружен, процесс завершается сбоем, поскольку в загруженное время память слишком велика. Я увеличил лимит памяти до 132 МБ, а max_execution_time - до 60 секунд. Но я все еще получаю случайные сбои при создании файла XML время от времени.

Что мне нужно сделать, чтобы сделать запрос быстрее? Я много читал о Transient API. Вы думаете, что это хорошая идея? Сторонний веб-сайт, которому я отправляю файл XML, запрашивает его каждые 1 час. Поэтому я выполнил задание cron для моего сервера по воссозданию XML каждые 1 час, чтобы в файле всегда были новые продукты или любое изменяемое значение.

Моя главная проблема - как мне сделать Запрашивает все варианты / переменные быстрее?

Вот как я строю XML на тот случай, если вы, ребята, считаете, что процесс неэффективен:

// Create the XML file
$myFile = fopen("skroutz.xml", "w+");

// XML Headers
$ex .= "<?xml version='1.0' encoding='UTF-8'?>";
$ex .= "<mywebstore>";
$ex .= "<created_at>" . date("Y-m-d H:i") . "</created_at>";
$ex .= "<products>";

// Loop through products
$loop = new WP_Query( array(
    'post_type' => 'product',
    'posts_per_page' => -1,
    'orderby' => 'title',
    'order' => 'ASC',
    'tax_query' => array( array(
        'taxonomy' => 'product_cat',
        'field' => 'id',
        'terms' => 113,
        'operator' => 'NOT IN'
    ) )
) );

if ( $loop->have_posts() ) : while ( $loop->have_posts() ) : $loop->the_post();

if ( $product->is_type( 'variable' ) ){  // Check if product is Variable

...

}

endwhile;
endif;
wp_reset_query();


$ex .= "</products>";
$ex .= '</mywebstore>';

fwrite($myFile, $ex);
fclose($myFile);

1 Ответ

1 голос
/ 31 января 2020

Итак, это не будет полностью рабочий (или протестированный) пример, но вы можете получить достаточно подсказок из этого:

define('XML_FILE', 'skroutz.xml');
define('QUERY_LIMIT', 500);
$query_offset = get_transient('xml_query_offset');
if (($query_offset === false) || !is_numeric($query_offset)) {
  // -- (re-)start the query initially, write a new XML file --
  $query_offset = 0;
  ob_start();
  // XML Headers
?>
<?xml version='1.0' encoding='UTF-8'?>
<mywebstore>
<created_at><?= date("Y-m-d H:i") ?></created_at>
<products>
<?php
  file_put_contents(XML_FILE, ob_get_clean()); // flush buffer to new XML file
}

// Loop through products (from $query_offset)
$loop = new WP_Query( array(
    'post_type' => 'product',
    'offset' => $query_offset,
    'posts_per_page' => QUERY_LIMIT,
    'orderby' => 'title',
    'order' => 'ASC',
    'tax_query' => array( array(
        'taxonomy' => 'product_cat',
        'field' => 'id',
        'terms' => 113,
        'operator' => 'NOT IN'
    ) )
) );

if ( $loop->have_posts() ) : while ( $loop->have_posts() ) : $loop->the_post();

if ( $product->is_type( 'variable' ) ){  // Check if product is Variable

...

}
file_put_contents(XML_FILE, $GENERATED_XML_CONTENT, FILE_APPEND); // append product's XML code to the end of the file

endwhile;
endif;

if (($query_offset + QUERY_LIMIT) >= $loop->found_posts) {
  // you've reached the end, delete the transient
  delete_transient('xml_query_offset');
  file_put_contents(XML_FILE, '</products>'.PHP_EOL, FILE_APPEND); // close the products XML tag, finally.
  // we're done.
} else {
  $query_offset += QUERY_LIMIT;
  set_transient('xml_query_offset', $query_offset, 5 * MINUTE_IN_SECONDS);
  // we will force a reload via JS (assuming the front-end output is HTML)
?>
<script>
location.reload(true); // bypass cache
</script>
<?php
}
wp_reset_query();

Общая идея состоит в том, чтобы определить, был ли запущен код в течение последних 5 минут (кратковременный тайм-аут). Если этого не произошло, это означает, что вы хотите сгенерировать новый XML -файл. Я лично предпочитаю использовать буферизацию вывода вместо добавления переменной $ex, записывающей это в файл. Затем вы можете использовать file_put_contents либо без FILE_APPEND для создания нового файла, либо просто добавить к уже существующему контенту.

Производительность записи в файл (неважно, в какую сторону) не ваше узкое место здесь, а скорее запрос WP и l oop. Это означает, что вы сокращаете l oop, ограничивая результаты. После завершения последнего блока вы закрываете тег XML и удаляете переходный процесс. Я не уверен, что эта неуклюжая JS автоперезагрузка действительно сработает или вам придется вручную вызывать ее снова.

...