У меня есть сайт, на котором есть десятки тысяч заказов, и мне нужно сравнить платежные и клиентские электронные письма и показать флаг, если они не совпадают. Одно из условий заключается в том, что я не могу добавить какие-либо метаданные в заказы. Поэтому мое решение состоит в том, чтобы просто добавить пользовательский столбец и сравнивать электронные письма на лету, когда отображается список заказов. Это прекрасно работает.
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 );
}
}
Я был бы очень признателен за понимание того, как можно сократить расходы на запрос, который я пытаюсь выполнить, или альтернативный подход. Опять же, просто для пояснения, добавление метаданных к заказам не вариант.
Спасибо!