wordpress查询19000多个产品

7hiiyaii  于 2021-06-19  发布在  Mysql
关注(0)|答案(1)|浏览(334)

我的wordpress查询有问题。
我要做的是:
我有一个csv文件,里面有产品数据(名称、价格、库存、sku等),我想导入这个文件,但是当我试图按sku获取产品id时,我的查询对于我的服务器来说太高了,但是我做了一些愚蠢的想法:在foreach中,我试图获取所有的产品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\u postmeta表有90多万条记录:o

nhhxz33t

nhhxz33t1#

我想导入这个文件
我没有看到任何用于导入的代码,我看到了用于显示的代码。假设导入是指显示:
可能发生的事情只是其中一件。
你的内存不足(你应该得到一个错误)
不要使用 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'])

基本上,这会寻求php能够处理的最大可能的int,但是由于文件是固定长度的,所以它会将指针放在文件的末尾,然后使用 `key` 我们可以查到电话号码。然后我们简单地回到我们想阅读的地方。
我提到总行数是因为在分页中能够显示这一点很好。
另一个选项(显示)
除此之外,分页是在没有缓冲的情况下输出页面。

// 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)。服务器将响应,然后您将再次调用(x)行,保存并重复。
我想显示所有产品的id,以检查它是否正确。下一步是改变库存,价格和节省产品
在excel之类的工具中做这项工作会更容易,只是从数据输入的Angular 来看,没有人希望编辑一个网页上的数千行,然后让他们的会话超时或诸如此类的事情。
希望有帮助。

相关问题