web-dev-qa-db-ja.com

get_posts/WP_Queryメモリサイズ134217728バイトを使い果たしました

商品ページのすべての投稿IDを取得したいです。しかし、最初の方法も2番目の方法も成功しています...

私はいつも得ます:

PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 8388616 bytes) in /var/www/vhosts/httpdocs/wp-includes/wp-db.php on line 1842

最初の方法:

if ( ! defined('ABSPATH') ) {
    /** Set up WordPress environment */
    require_once( dirname( __FILE__ ) . '/wp-load.php' );
}

$posts_array = get_posts(array(
            'post_type' => 'product',
            'posts_per_page' => -1
        ));

$myfile = fopen("wp_all_import.txt", "a");

foreach ($posts_array as $value) {
    fwrite($myfile, $posts_array . "\n");
}

fclose($myfile);

第二の方法:

if ( ! defined('ABSPATH') ) {
    /** Set up WordPress environment */
    require_once( dirname( __FILE__ ) . '/wp-load.php' );
}

$products_IDs = new WP_Query( array(
            'post_type' => 'product',
            'posts_per_page' => -1
        ));
$myfile = fopen("wp_all_import.txt", "a");

while ($products_IDs->have_posts() ) : $products_IDs->the_post();
fwrite($myfile, get_the_ID() . "\n");
endwhile; wp_reset_query();

fclose($myfile);

誰が私の失敗がどこにあるのか、そしてどうすればそれを修正できるのか知っていますか?商品投稿の投稿IDをすべて取得したいだけです。

ご挨拶とありがとう!

4
Jan
  1. 必要なのがファイルにIDを印刷することだけであれば、それからそれに対するカスタムクエリを書くことができます。そうすれば、WordPressのような内部処理を避けることができます。

  2. 2100の投稿からIDを選択しただけでは、134MBのRAMが消費されるとは思いませんが、多くの投稿でRAMが枯渇することがあります。 IDはたった1バイトで保存することができますが、それが4バイトかかることを言いましょう。それでも、2100 x 4 = 8400バイト= 8.4 KBです。 PHPは、処理するため、オブジェクトを作成するためなど、より多くの内部メモリを必要とします。しかし、134MBのメモリを使えば、簡単に数十万のIDを処理できます。だから明らかにあなたはどこか他の場所で間違っています。

とにかく、どんな理由であれ(IDだけでなくproductからすべてを選択する必要があるかもしれません)、あなたは制限でクエリを分割することができます。次のコードのように:

if ( ! defined('ABSPATH') ) {
    /** Set up WordPress environment */
    require_once( dirname( __FILE__ ) . '/wp-load.php' );
}
// $limit determines how many rows you want to handle at any given time
// increase / decrease this limit to see how much your server can handle at a time 
$limit = 100;
$start = 0;

// open file handle
$myfile = fopen( dirname( __FILE__ ) . '/wp_all_import.txt', 'a' );

$qry = "SELECT ID FROM `$wpdb->posts` where post_type='post' AND post_status='publish' limit %d, %d";
while( $result = $wpdb->get_results( $wpdb->prepare( $qry, array( $start, $limit ) ) ) ) {
    $write_data = '';
    foreach ( $result as $row ) {
        $write_data = $write_data . $row->ID . "\n";
    }
    // Generally speaking, writing immidiately to the file is better than
    // string concatination, because depending on what you concat and how many times,
    // the generated string may become too big (like MB size string).
    // On the other hand, writing to files thousands of times in a single script may
    // cause I/O delays. So, here I've done a combination of the two to keep both
    // string size & I/O within limits.
    // Adjust this according to your own situation.
    fwrite( $myfile, $write_data );
    $start = $start + $limit;
}

// close file handle
fclose( $myfile );

このようにPHPは最大$limit行の数だけを扱うので、メモリの制限を超えるべきではありません。

注: 非常に長い文字列(MBの長さなど)を作成するために連結することはありません。ファイルが長くなる前にすぐにファイルに書き込んでください。多少のI/O遅延が生じる可能性がありますが、メモリの制限を超えることはありません。

4
Fayaz