Большой запрос WooCommerce выбрасывает фатальные ошибки памяти - PullRequest
2 голосов
/ 12 апреля 2020

У меня есть сайт, на котором есть десятки тысяч заказов, и мне нужно сравнить платежные и клиентские электронные письма и показать флаг, если они не совпадают. Одно из условий заключается в том, что я не могу добавить какие-либо метаданные в заказы. Поэтому мое решение состоит в том, чтобы просто добавить пользовательский столбец и сравнивать электронные письма на лету, когда отображается список заказов. Это прекрасно работает.

add_filter( 'manage_edit-shop_order_columns', 'mismatched_orders_column' ); 

function mismatched_orders_column( $columns ) {

    $columns['mismatched'] = 'Mismatched';
    return $columns;

}

add_action( 'manage_shop_order_posts_custom_column', 'mismatched_orders_column_data' );

function mismatched_orders_column_data( $column ) {

    global $post;

    if ( 'mismatched' === $column ) {

        $order    = new WC_Order( $post->ID );
        $customer = $order->get_user();

        $result = '';

        $billing_email = strtolower ( $order->get_billing_email() );
        $customer_email = '';

        if ($customer) $customer_email = strtolower ( $customer->user_email );

        if ( $customer && ( $billing_email != $customer_email ) ) {

            $result = '<span class="mismatched-order" title="Possible order mismatch">Yes</span>';

        }

        echo $result;
    }
}

Моя проблема при попытке добавить сортировку. Поскольку у меня нет доступа к каким-либо метаданным записей, у меня нет простых данных для сортировки по основному запросу. Первоначально мое решение заключалось в том, чтобы подключиться к pre_get_posts, захватить все заказы в новом WP_Query, затем l oop через них и добавить те, которые имели несоответствующие электронные письма, в массив для использования в post__in.

Это работает / отлично работает на моем маленьком сайте разработчиков, но выдает фатальные ошибки памяти при попытке l oop на более чем 8 или 9 тысяч постов (из общего количества 30-40 тысяч). Увеличение памяти на самом деле не вариант.

add_filter( 'manage_edit-shop_order_sortable_columns', 'mismatched_orders_column_sortable');

function mismatched_orders_column_sortable( $columns ) {
    $columns['mismatched'] = 'mismatched';
    return $columns;
}

add_action( 'pre_get_posts', 'mismatched_emails_posts_orderby' );

function mismatched_emails_posts_orderby( $query ) {

    if( ! is_admin() || ! $query->is_main_query() ) {
        return;
    }

    //Remove the pre_get_posts hook so we don't get stuck in a loop
    add_action( 'pre_get_posts', 'mismatched_emails_posts_orderby' );

    //Make sure we're only looking at our custom column
    if ( 'mismatched' === $query->get( 'orderby') ) {

        //Set our initial array for 'post__in'
        $mismatched = array();

        $orders_list = get_posts(array(
            'post_type'         => 'shop_order',
            'posts_per_page'    => -1,
            'post_status'       => 'any',
            'fields'            => 'ids'
        ));

        //And here is our problem
        foreach( $orders_list as $order_post ) :

            //Get our order and customer/user object
            $order_object = new WC_Order( $order_post );
            $customer = $order_object->get_user();

            //Check that billing and customer emails don't match, and also that we're not dealing with a guest order
            if ( ( $order_object->get_billing_email() != $customer->user_email ) && $order_object->get_user() != false ) {

                $mismatched[] = $order_post;

            }

        endforeach;  wp_reset_postdata();

        $query->set( 'post__in', $mismatched );

    }
}

Я был бы очень признателен за понимание того, как можно сократить расходы на запрос, который я пытаюсь выполнить, или альтернативный подход. Опять же, просто для пояснения, добавление метаданных к заказам не вариант.

Спасибо!

...