Wordpress запрос с более чем 19000 продуктов - PullRequest
0 голосов
/ 22 октября 2018

У меня проблема с моим Wordpress Query.

Что я пытаюсь сделать:

У меня есть CSV-файл с данными о товарах (название, цена, запас, артикул и т. Д.) ИЯ хочу импортировать этот файл, но когда я пытаюсь получить Product ID по SKU, мой запрос слишком высок для моего сервера, но я делаю глупую идею: в foreach я пытаюсь получить все product_id.

Можно ли разделить мой wp-запрос, не убивая мой сервер?Я пытаюсь спать, но это не результат ...

Мой код здесь:

    public function new_import_stock_prices(){
    global $wpdb;
    global $post;

    if ( !function_exists( 'wc_get_product_id_by_sku' ) ) { 
        require_once '/includes/wc-product-functions.php'; 
    } 

    echo '<h1>Import stanów magazynowych i cen z pliku CSV </h1>';
    echo '<h4>Plik pobierany jest z netis/products.csv</h4>';
    $fn = 'https://e-xxxxx.pl/xxx/products.csv';
    $file_array = file($fn);
    echo '<table>';
    echo '<tr>';
    echo '<td>LP</td>';
    echo '<td>Nazwa</td>';
    echo '<td>SKU</td>';
    echo '<td>Stan magazynowy</td>';
    echo '<td>Cena</td>';
    echo '<td>Product ID</td>';
    $i = 1;
    if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {

    foreach ($file_array as $line_number =>&$line)
        {
            if ($line_number > 0 && $line_number % 10 == 0) {

                $row2=explode('|',$line);
                $sku = $row2[1];
                // get the product ID from the SKU
                $product_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value='%s' LIMIT 1", $sku ) );        
                // Get an instance of the WC_Product object
                $product = new WC_Product( $product_id );

                //Get product stock quantity and stock status
                $stock_quantity = $product->get_stock_quantity();
                $stock_status   = $product->get_stock_status();

                echo '<tr>';
                echo '<td>'.$i.'</td>';
                echo '<td>'.$row2[0].'</td>';
                echo '<td>'.$row2[1].'</td>';
                echo '<td>'.$row2[5].'</td>';
                echo '<td>'.$row2[2].'</td>';
                echo '<td>'.$product_id.'</td>';

                echo '</tr>';
                $i = $i +1;
                sleep(10);
            }
        }
    }
    echo '</table>';
}

Кстати.моя таблица wp_postmeta содержит ~ 900 000+ записей: O

1 Ответ

0 голосов
/ 22 октября 2018

И я хочу импортировать этот файл

Я не вижу кода для импорта, я вижу код для отображения.Предполагая, что при импорте вы имеете в виду отображение:

То, что, вероятно, происходит, является одной из нескольких вещей.

  • нехватка памяти (вы должны получить сообщение об ошибке)
    • не используйте file($fn) используйте файловые функции, которые открывают файл и читают построчно, такие как fgetcsv
  • ваше время истекло
    • Вы не можете ничего с этим поделать, за исключением отправки меньшего количества данных
  • вашего подавляющего буфера браузера, посылая много выходных данных.
    • опять же, вы мало что можете с этим поделать, но отправляете меньше данных.

Единственное реальное решение (при импорте вы имеете в виду отображение) - это страницаданные.

Теперь даже в файле вы можете публиковать данные, но я бы предложил использовать SQLFileObject вместо процедурных файловых функций.Тем не менее, вы можете создавать страницы, используя процедурный стиль, но с байтовым смещением, а не номером страницы.

Хотя я не могу кодировать всю систему подкачки, я могу дать вам несколько советов:

Например

//hard to tell how many lines in the file
$fn = 'https://e-xxxxx.pl/xxx/products.csv';
$f = fopen($fn, 'r');
fseek($f, $_GET['offset']); //seek to a byte offset
$i=0;
while(!feof($f) && ($row=fgetcsv($f)) && null !== $row[0]){

   if($i==10)
       $offset = ftell($f); //get byte offset

   ++$i;
}

ftell и fseek позволяют получить или переместить указатель файла (в байтах).Таким образом, вы можете начать чтение с предопределенного смещения, которое можно передать в URL-адресе ... и т. Д.

Вы можете сделать то же самое с SplFileObject, но немного лучше.

try {
    $fn = 'https://e-xxxxx.pl/xxx/products.csv';
    $csv  = new SplFileObject($fn, 'r');
} catch (RuntimeException $e ) {
    printf("Error openning csv: %s\n", $e->getMessage());
}

$csv->seek($_GET['line']); //seek to a predefined line

while(!$csv->eof() && ($row = $csv->fgetcsv()) && null !== $row[0]) {
    if(($csv->key()-$_GET['line'])==10) 
        $line = $csv->key(); //get line offset
   ++$i;
}

Основным преимуществом SPL является то, что вы можете использовать номер строки, с которым намного проще работать.

Вы также можете получить общее количество строк в файле, подобном этому

$csv->seek(PHP_INT_MAX);
$total = $csv->key();
$csv->rewind(); //or $csv->seek($_GET['line'])

В основном это стремится к максимально возможному INT, который PHP может обработать, но поскольку файл имеет фиксированную длину, он помещает указатель в конец файла, а затем, используя key, мы можем получить номер строки.Затем мы просто перематываем туда, откуда хотим читать.

Я упоминаю общее количество строк, потому что в разбивке по страницам приятно иметь возможность показать это.

Другой вариант (дляdisplay)

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

 // Turn off output buffering
 ini_set('output_buffering', 'off');
 // Turn off PHP output compression
 ini_set('zlib.output_compression', false);

 //Flush (send) the output buffer and turn off output buffering
 //ob_end_flush();
 while (ob_get_level()) ob_end_flush();

 // Implicitly flush the buffer(s)
 ini_set('implicit_flush', true);
 ob_implicit_flush(true);

Объедините это с одним из методов, которые я показал выше, чтобы прочитать файл по одной строке за раз, и вы сможете в конечном итоге прочитать все эти данные.

Сохранение

Для сохранения данных вам, вероятно, понадобится разбить их на партии, то же самое можно сделать с подкачкой страниц (с использованием смещения или строки).Так что вы можете импортировать только пару тысяч строк одновременно.Я также рекомендовал бы не выводить данные, потому что вы можете дать браузеру больше буфера, чем он может обработать и заблокировать.Однако, если вы разместите данные на странице, вы можете разбить их на достаточно маленькие куски, чтобы браузер смог их обработать.

Вы можете даже автоматизировать это, используя последовательные вызовы AJAX.В основном вы должны вызывать код на бэкэнде, чтобы сохранить определенное количество строк (х).Сервер ответит, и затем вы сделаете еще один вызов для (x) большего количества строк, сохраните и повторите.

Я хочу отобразить идентификатор всех продуктов, чтобы проверить, правильно ли это.Следующим шагом является изменение запасов, цены и сохранение продуктов

Было бы проще выполнить эту работу в чем-то вроде Excel, просто с точки зрения ввода данных, никто не хочет редактировать тысячи строк в Интернетестраницы, а затем время их сеанса или что-то вроде этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...