Упорядочение по нескольким пользовательским мета-полям


У меня есть пользовательский тип записи в моем плагине с именем members, а также два пользовательских поля; first_name и last_name. Я пытаюсь упорядочить свой список по фамилии, затем по имени. Единственное решение, которое я нашел, - это то, которое использует функцию для извлечения первых двух мета-полей запроса и заменяет их (я следовал учебнику по dotnordic.se). Однако всякий раз, когда я пытаюсь это сделать, мне не возвращаются сообщения. Я опубликовал свой код ниже. Любая помощь в устранении проблемы, которая у меня есть с моим код или предложение другого способа очень ценятся.

  // Shortcode Function
  function mba_members_list_code() {

  // WP_Query arguments
  $args = array (
  'post_type'       => 'member_data',
  'post_status'     => 'active',
  'fields'          => 'ids',
  'posts_per_page'  => -1,
  'meta_key'        => 'last_name',
  'orderby'         => 'meta_value',
  'order'           => 'ASC',
  'meta_query'      => array(
    array(
      'key'         => 'first_name',
    ),
    array(
      'key'         => 'last_name',
    ),
    array(
      'key'         => 'publicly_listed',
      'value'       => 'true',
    ),
  ),
);

// The Query
$posts = get_posts( $args );

// The Loop
if( $posts ) {
   echo "Total Members Found: " . count($posts) . "<br>";

   foreach ( $posts as $post ) {
      $q = get_post_meta($post);
      echo "<b>" . $q['first_name'][0] . " " . $q['last_name'][0] . "</b><br>";
      echo $q['city'][0] . ", " . $q['state'][0] . " " . $q['zip'][0] . "<br>";
      echo "<a href='mailto:" . $q['email'][0] . "'>" . $q['email'][0] . "</a><br>";
      echo "<br>"; 
   }
   unset( $post );       
}else{
  echo "<b>Sorry, we found no active members. Please be sure to check back soon.</b>";
}
}

РЕДАКТИРОВАТЬ

function customorder($orderby) {
global $wpdb;
return ' {$wpdb->postmeta}.meta_value, mt1.meta_value';
//return str_replace('menu_order', 'mt1.meta_value, mt2.meta_value', $orderby);
}

Я знаю, что есть и другие вопросы по этому поводу с ответом на реализацию этой же функции; однако всякий раз, когда я ее реализую, у меня нет записей/сообщений.

Author: Michael, 2014-10-26

2 answers

РЕДАКТИРОВАТЬ ( Пожалуйста, ознакомьтесь с оригинальным ответом для полного объяснения кода)

Код в моем первоначальном ответе работает должным образом, но вызывает известную ошибку с usort (Проверьте отчет об ошибке здесь #50688)

Ошибка предупреждения: [2] usort(): Массив был изменен функцией сравнения пользователей

Эта ошибка срабатывает только тогда, когда параметр fields задан в аргументах в get_posts, поэтому единственным приемлемым обходным путем я можно было найти, чтобы удалить параметр fields и перейти к извлечению полных записей.

Вот рабочая версия без ошибок

<?php
$args = array (
  'post_type'              => 'member_data',
  'post_status'            => 'active',
  'posts_per_page'         => -1,
  'meta_query'             => array(
    array(
      'key'       => 'first_name',
    ),
    array(
      'key'       => 'last_name',
    ),
    array(
      'key'       => 'publicly_listed',
      'value'     => 'true',
    ),
  ),
);

$posts = get_posts( $args );

usort( $posts, function( $a, $b ){

    // sort first by last name
    $compare = strnatcmp(get_post_meta($a->ID, 'last_name', true), get_post_meta($b->ID, 'last_name', true));

    // if last names are identical, sort by first name
    if(!$compare) {
        return strnatcmp(get_post_meta($a->ID, 'first_name', true), get_post_meta($b->ID, 'first_name', true));
    }else{
        return $compare;
    }

});

if( $posts ) {
   echo "Total Members Found: " . count($posts) . "<br>";

   foreach ( $posts as $post ) {
      $q = get_post_meta($post->ID);
      echo "<b>" . $q['first_name'][0] . " " . $q['last_name'][0] . "</b><br>";
      echo $q['city'][0] . ", " . $q['state'][0] . " " . $q['zip'][0] . "<br>";
      echo "<a href='mailto:" . $q['email'][0] . "'>" . $q['email'][0] . "</a><br>";
      echo "<br>"; 
   }
   unset( $post );       
}else{
  echo "<b>Sorry, we found no active members. Please be sure to check back soon.</b>";
}
}

ОРИГИНАЛЬНЫЙ ОТВЕТ

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

  • Используйте WP_Query или даже лучше get_posts извлекайте свои сообщения в обычном режиме. На этом этапе нет необходимости применять какую-либо сортировку. По моему личному мнению, это бесполезно поскольку вы можете сортировать только по одному meta_value, а не по двум. Я бы предпочел просто использовать сортировку php для упорядочивания сообщений по мере необходимости. (Если вы собираетесь использовать разбивку на страницы, лучше используйте WP_Query).

  • Вы собираетесь использовать usort для сортировки своих сообщений, сначала по last_name, затем, если два или более человека используют один и тот же last_name, мы будем сортировать в соответствии с first_name.

Вот концепция:

Прежде чем я начну, я хочу указать на несколько вещей

  • Ваш meta_query - это к сожалению, беспорядок. Все находится внутри массива внутри массива внутри массива, где, как и должно быть, 3 отдельных массива внутри одного массива

  • Я бы предпочел использовать get_posts здесь, а также извлекать только идентификаторы сообщений, поскольку вы не собираетесь использовать какие-либо данные postdata или любые другие данные, возвращаемые WP_Query

  • Это довольно сложная операция, так как бд посещается два раза для каждого поста. Вам придется постараться использовать здесь переходные процессы.

Теперь о решении

Как сказано, используйте get_posts для построения вашего запроса. Мы собираемся получить сообщения, которые соответствуют всем трем meta_key

$args = array (
  'post_type'              => 'member_data',
  'fields'                 => 'ids',
  'post_status'            => 'active',
  'posts_per_page'         => -1,
  'meta_query'             => array(
    array(
      'key'       => 'first_name',
    ),
    array(
      'key'       => 'last_name',
    ),
    array(
      'key'       => 'publicly_listed',
      'value'     => 'true',
    ),
  ),
);

$posts = get_posts( $args );

Теперь мы будем сортировать $posts по last_name, а затем first_name с помощью usort

usort( $posts, function( $a, $b ){

    // sort first by last name
    $compare = strnatcmp(get_post_meta($a, 'last_name', true), get_post_meta($b, 'last_name', true));

    // if last names are identical, sort by first name
    if(!$compare) {
        return strnatcmp(get_post_meta($a, 'first_name', true), get_post_meta($b, 'first_name', true));
    }else{
        return $compare;
    }

});

$posts теперь должны быть отсортированы в алфавитном порядке по last_name, и если last_name одинаковы для двух или более лиц, они будут отсортированы в алфавитном порядке по first_name.

Теперь ваш цикл будет следовать и выглядит так

if( $posts ) {
   echo "Total Members Found: " . count($posts) . "<br>";

   foreach ( $posts as $post ) {
      $q = get_post_meta($post);
      echo "<b>" . $q['first_name'][0] . " " . $q['last_name'][0] . "</b><br>";
      echo $q['city'][0] . ", " . $q['state'][0] . " " . $q['zip'][0] . "<br>";
      echo "<a href='mailto:" . $q['email'][0] . "'>" . $q['email'][0] . "</a><br>";
      echo "<br>"; 
   }
   unset( $post );       
}else{
  echo "<b>Sorry, we found no active members. Please be sure to check back soon.</b>";
}
}
 0
Author: Pieter Goosen, 2014-11-03 03:49:24

Попробуйте что-то подобное из другого поста:

query_posts(
    array( 
        'post_type'      => 'custompost', 
        'posts_per_page' => 4, 
        'meta_key'       => 'mydate', 
        'orderby'        => 'meta_value', 
        'order'          => 'ASC', 
        'meta_query'     => array( 
            array( 
                'key'        => 'mydate', 
                'meta-value' => $value, 
                'value'      => $today, 
                'compare'    => '>=', 
                'type'       => 'CHAR' 
            ) 
        ) 
    )
);

Хотя вам нужно только отсортировать по фамилии, так как имя будет найдено в цикле в порядке, в котором вы его называете.

 0
Author: Tom Bangham, 2014-10-27 00:41:00