web-dev-qa-db-ja.com

カスタムWordPressループで疑わしいメモリの問題を解決するにはどうすればいいですか?

「どこで私たちについて聞きましたか」を追加するプラグインを書きました。 WooCommerceのチェックアウトページに質問し、その結果を(単純な横棒グラフとして)wp-adminページに表示します。

プラグインは問題なく動作していましたが、私が書いたときから動作を停止しています - メモリの問題のためです。

私のwp-config.phpファイルには... define('WP_MEMORY_LIMIT', '128M'); ...があり、また256MB512MBおよび1Gを試しましたが、これらは問題を解決しません。

phpinfo()memory_limit1Gを報告します - それでそれは問題ないようです。

だからここに私のプラグインのための関数はPHPがあきらめるように見えるところです:

function get_customer_sources() {

    $args = array(
        'post_type' => 'shop_order',
        'post_status' => 'publish',
        'posts_per_page' => -1,
        'tax_query' => array(
            array(
                'taxonomy' => 'shop_order_status',
                'field' => 'slug',
                'terms' => array('processing', 'completed', 'cancelled', 'failed', 'refunded')
            )
        )
    );

    //$custom_posts = new WP_Query($args);
    global $post; // required
    $custom_posts = get_posts($args);

    $all_sources = array(); //The return array
    echo "<h1>START</h1>";

    //while ($custom_posts->have_posts()) : $custom_posts->the_post();
    //if ( $custom_posts->have_posts() ) : while ( $custom_posts->have_posts() ) : $custom_posts->the_post();
    foreach($custom_posts as $post) : setup_postdata($post);


        //echo "<h2>A</h2>";

        $order_id = $post->ID;

        //echo "<h3>Order ID: $order_id</h3>";

        if ( get_post_meta($order_id, 'Where did you hear about us', true) ) {

            $source = get_post_meta($order_id, 'Where did you hear about us', true);

            //echo '<h4>Order ID: ' . $order_id . ': ' . $source . '</h4>';

            // Fix the "Vegan event" vs "Vegan Event" problem
            $source = ucfirst(strtolower($source));

            // Add the source to the return array
            if (array_key_exists($source, $all_sources)) {
                // Increment existing value
                $num = $all_sources[$source];
                $all_sources[$source] = $num + 1;
            }
            else {
                // Add value
                $all_sources[$source] = 1;
            }

            //echo '<h4>Num sources: ' . count($all_sources) . '</h4>';

        }

        //echo "<h2>B</h2>";

    //endwhile;
    //endwhile; endif;
    endforeach;

    echo "<h1>END</h1>";

    return $all_sources;
}`

私は物事をめちゃくちゃにしていたいくつかの悪いデータがあるかもしれないと思ったので、私は変更しました...

if ( get_post_meta($order_id, 'Where did you hear about us', true) ) {

...行...

if ( $order_id < 5000 && get_post_meta($order_id, 'Where did you hear about us', true) ) {

…そしてそれはうまくいった。

次に、その行を...に変更しました。

if ( $order_id >= 5000 && get_post_meta($order_id, 'Where did you hear about us', true) ) {

...それでもまだうまくいった。

しかし5000条件がなければ、スクリプトは爆弾を投げかけるだけです。 (<h1>END</h1>が出力されないのでこれを知っています。)

それでは、私のコードの何が問題になっていますか?あるいは、この方法が完了しないという問題をどのように解決すればよいでしょうか。例えば、それはメモリに関してより効率的に書かれることができましたか?それとももっと良いアプローチがありますか? (コメントアウトされていることから、WP_Queryを使用してみたことがわかりますが、同じ結果が得られます。)

NB - およそあります。クエリによって返された10,000項目。

前もって感謝します。

1

約あります。クエリによって返された10,000項目。

それはあなたの問題です。ループ内で何をしても、WordPressはまだオブジェクトをメモリにロード10,000しています。

それをまとめて、クエリ引数にちょっとした魔法を振りかけます。

$args = array(
    'fields'         => 'ids', // MAGIC! Just get an array of id's, no objects committed to memory
    'posts_per_page' => 500,   // Batch size: big enough to reduce meta queries, small enough not to hammer memory
    'post_type'      => 'shop_order',
    'post_status'    => 'publish',
    'tax_query'      => array(
        array(
            'taxonomy' => 'shop_order_status',
            'field' => 'slug',
            'terms' => array( 'processing', 'completed', 'cancelled', 'failed', 'refunded' ),
        )
    )
);

$query = new WP_Query;
$paged = 1;
$count = 0;
$total = null;

do {
    $args['no_found_rows'] = isset( $total ); // No need to SQL_CALC_FOUND_ROWS on subsequent iterations
    $args['paged'] = $paged++;

    $post_ids = $query->query( $args );
    update_postmeta_cache( $post_ids ); // Get all meta for this group of posts

    if ( ! isset( $total ) )
        $total = $query->found_posts;

    $count += $query->post_count;

    foreach ( $post_ids as $post_id ) {
        $source = get_post_meta( $post_id, 'Where did you hear about us', true );

        // Do your stuff here



        // Wipe this post's meta from memory
        wp_cache_delete( $post_id, 'post_meta' );
    }

} while ( $count < $total );
4
TheDeadMedic