Запитайте, щоб спочатку сортувати список за мета-ключами (якщо він існує) та показувати залишки публікацій без мета-ключа, упорядкованого за заголовком


22

Я працюю над шаблоном сторінки терміна користувальницької таксономії, де ми хочемо, щоб елементи, пов’язані з терміном, відсортовані за датою публікації (спеціальне поле дати) - і якщо в один день є кілька елементів (відформатованих як РРРР-ММ- DD), щоб потім сортувати їх за заголовком і, нарешті, сортувати за заголовком, якщо спеціальне поле не було заповнене (старі елементи).

Отже, я спробував це сто різними способами за допомогою WP_query, і він повертає більшість результатів так, як мені хочеться, але в цьому випадку це лише повернення елементів, які мають мета-ключ публікації_дачі. Усі інші елементи ігноруються та не відображаються. Я спробував meta_query, використовуючи співвідношення "або" і порівняв публікацію_date як EXISTS, а не EXISTS, але це повернуло 0 результатів для мене.

Також на сайті працює версія 3.5.2, і вони не хочуть оновлюватись.

Ось мій останній запит, який отримує мені публікації, у яких у правильному порядку відображається користувацьке поле публікації_дані:

$term = get_queried_object(); // find the term of the taxonomy page we are on
$wp_query = new WP_Query( array(
'post_type' => 'resource',
'tax_query' => array(
    array(
        'taxonomy' => 'resource_types',
        'field' => 'slug',
        'terms' => $term->name,
    )), 

'meta_key' => 'publication_date',
'orderby' => 'meta_value_num',
'order' => 'DESC',
'paged' => $paged,
'posts_per_page' => '10',
));

Я також спробував використовувати wpdb та запустити SQL-запит, але я дійсно не впевнений, як досягти того, що я хочу робити. Якби хтось міг мені допомогти, це було б приголомшливо!

Заздалегідь спасибі.


Здивований підхід meta_query не спрацював, але знову ж таки ви не можете замовити мета-значення мета_query без встановлення meta_key.
sanchothefat

Я думаю, що це проблема у мене. Нарешті, мета запит працює: 'meta_query' => array( 'relation' => 'OR', array( //check to see if date has been filled out 'key' => 'publication_date', 'compare' => '!=', 'value' => date('Y-m-d'), ), array( //if no date has been added show these posts too 'key' => 'publication_date', 'value' => date('Y-m-d'), 'compare' => 'NOT EXISTS' ) ),але замовлення не працює: \
CSSgirl

Так, на замовлення, на жаль, покладається мета-ключ, встановлений поза податковим запитом. Моя відповідь нижче може допомогти.
sanchothefat

Відповіді:


19

Дякую всім за допомогу!

Зрештою, запит нижче отримав мені бажані результати - який повинен був показати та сортувати публікації за власним полем "публікація_дачі" спочатку - сортування за датою, і якщо їх було декілька однієї дати (скажімо, 4 позначені Червень 2013 року), вони б сортували їх за назвою. Потім, після проходження всіх публікацій, у яких заповнена дата публікації, вона знову перегляне решту публікацій, в алфавітному порядку за заголовком.

Це дає мені результати, встановлені в одному запиті, і зберігає мою сторінку:

$term = get_queried_object();
the_post();
$wp_query = new WP_Query( array(
'post_type' => 'resource',
    'tax_query' => array(
        array(
            'taxonomy' => 'resource_types',
            'field' => 'slug',
            'terms' => $term->name,
        )),
 'meta_query' => array(
       'relation' => 'OR',
        array( //check to see if date has been filled out
                'key' => 'publication_date',
                'compare' => '=',
                'value' => date('Y-m-d')
            ),
          array( //if no date has been added show these posts too
                'key' => 'publication_date',
                'value' => date('Y-m-d'),
                'compare' => 'NOT EXISTS'
            )
        ),
'meta_key' => 'publication_date',
'orderby' => 'meta_value title',
'order' => 'ASC',
'paged' => $paged,
'posts_per_page' => '10',
));

1
Приємно. Я ніколи не думав запускати двох meta_queryза одним ключем!
GhostToast

5
Для мене (використовуючи WordPress 4.1.1), якщо я встановив meta_keyйого автоматично, він не включає його навіть NOT EXISTS. Я дуже сподіваюся, що роблю щось не так.
Райан Тейлор

1
@RyanTaylor тут же - meta_key не повинен встановлюватися в запиті, щоб це працювало, але воно, схоже, впорядковується правильно за мета-значенням, навіть коли мета-ключ не встановлений.
jammypeach

2
Як зазначено вище, для WP 4.1+ вилучіть або коментуйте 'meta_key' => 'publication_date',.
MikeiLL

7

Через кілька років код, опублікований CSSGirl, не працював для мене, оскільки там були деякі дописи, у яких не було мета-ключа або мета-ключ був порожній, тому це мені довелося зробити, щоб усі повідомлення були упорядковані за датою і спочатку покажіть ті, на яких відображається значення мета-ключа:

$args          = array(
'post_type'   => $type,
'post_status' => 'publish',
'nopaging'    => TRUE,
'meta_query'  => array(
    'relation' => 'OR',
    array(
        'key'     => $meta_key,
        'compare' => 'NOT EXISTS',
    ),
    array(
        'relation' => 'OR',
        array(
            'key'   => $meta_key,
            'value' => 'on',
        ),
        array(
            'key'     => $meta_key,
            'value'   => 'on',
            'compare' => '!=',
        ),
    ),
),
'orderby'     => array( 'meta_value' => 'DESC', 'date' => 'DESC' ),
);

1

Я думаю, вам знадобиться зробити дві окремі петлі. Ви можете захопити всі повідомлення, знайдені в першому циклі, і досить легко їх виключити з вторинного циклу:

$found_posts = array();
while($loop->have_posts()): $loop->the_post();
    // loop stuff
    $found_posts[] = get_the_id();
endwhile;

wp_reset_query();

$args = array(
    // other args
    'post__not_in' => $found_posts,
);

Потім запустіть свою другу петлю.


Спробую це зараз, дякую. Повідомляю, чи працює!
CSSgirl

1
це спрацювало - але воно порушило сторінку, - будь-яка ідея, як змусити це працювати? Ось як це виглядає зараз:echo paginate_links( array( 'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ), 'format' => '?page=%#%', 'current' => max( 1, get_query_var('paged') ), 'total' => $publication_query->max_num_pages, 'prev_text' => __('Previous |'), 'next_text' => __('| Next'), ) );
CSSgirl

Хм. Не те, що я можу придумати.
GhostToast

1

Чи є якась причина, що ви не змогли примусити мета-ключ публікації_давця існувати для кожної публікації лише з порожнім значенням?

Тож у вашій save_postдії ви б додавали / оновлювали мета-ключ, $_POSTзначення чи порожнє чи ні.

Вам потрібно буде запустити сценарій оновлення, щоб перейти на старі повідомлення та додати ключ із порожнім значенням, наприклад:

add_action( 'admin_init', 'update_old_posts' );
function update_old_posts() {
    if ( ! isset( $_GET[ 'update_old_posts' ] ) )
         return;

    foreach( get_posts() as $post ) {
        if ( false === get_post_meta( $post->ID, 'publication_date', true ) ) {
             update_post_meta( $post->ID, 'publication_date', '' );
             echo "Updated {$post->post_title} <br />";
        }
    }

    die;
}

Запустити його, переглянувши http://example.com/wp-admin/?update_old_posts

Тоді ви можете використовувати той самий запит, що і у вас. Ви можете додати додатковий фільтр, щоб ви могли замовляти різні стовпці в різних напрямках, мені було б доцільно сортувати за датою у порядку зменшення та за заголовком у порядку зростання.

add_filter( 'posts_orderby', 'multicolumn_orderby', 10, 2 );
function multicolumn_orderby( $orderby, $query ) {
    global $wpdb;

    // check it's the right query
    if ( $query->get( 'meta_key' ) == 'publication_date' ) {
         $orderby = "$wpdb->postmeta.meta_value+0 DESC, $wpdb->posts.post_title ASC";
    }

    return $orderby;
}

Хм, я не думав про це. Я спробую спробувати і побачити, як це відбувається, дякую!
CSSgirl

0

Я створив звичай, де застереження. Я перевірив це за допомогою $wp_query->requestпрямого мого основного циклу, я не дуже добре знаю SQL, але, здавалося, це спрацювало.

add_action('pre_get_posts', 'add_trending_sort', 11, 1);
function add_trending_sort($query){
  if(!$query->is_main_query())
    return;

  //Overwrite query arguments
  $query->set('meta_query', array(
    array(
      'key' => 'TRENDING',
      //'value' => 'asdfasdf',//may need a value for older versions of WordPress
      'compare' => 'NOT EXISTS',
    )
  ));
  $query->set('orderby', 'meta_value_num date');
  $query->set('order', 'DESC');
}

add_filter('posts_where', 'add_trending_where');
function add_trending_where($where = ''){
  global $wpdb, $wp_query;
  if(!$wp_query->is_main_query())//Not sure if this really works.  Should be OK
    return $where;

  $where .= " OR ( $wpdb->postmeta.meta_key = 'TRENDING' )";

  // Don't run this twice
  remove_filter('posts_where', 'add_trending_where');

  return $where;
}

Як альтернативи, ви можете встановити compareна 'EXISTS'і змінити рядок в add_trending_where до $where .= " OR ($wpdb->postmeta.post_id IS NULL)";. Тоді вам доведеться лише змінити значення ключа в одному місці. Знову повторіть $wp_query->requestі пограйте, якщо ви хочете зрозуміти це краще або налаштуйте його.

EDIT: Я щойно помітив, що це не працює, якщо meta_keyвстановлено запит. Ви можете використовувати, $query->set('meta_key', NULL);якщо вам доведеться.

EDIT 2: Я працював із вищезгаданим методом. Чомусь спочатку це не було (можливо, було встановлено мета_кей ... я не знаю).

add_action('pre_get_posts', 'add_trending_sort', 11, 1);
function add_trending_sort($query){
  // Bail if not the main "hidden" query, as opposed to a 'new WP_Query()' call
  if(!$query->is_main_query())
    return;

  // Set meta_query to get shares for orderby, and also get non-shared content.
  $query->set('meta_query', array(
    'relation' => 'OR',
    array(
      'key' => 'TRENDING',
      'compare' => 'NOT EXISTS',
    ),
    array(
      'key' => 'TRENDING',
      'compare' => 'EXISTS',
    )
  ));
  //$query->set('meta_key', NULL);
  $query->set('orderby', array('meta_value_num' => 'DESC', 'date' => 'DESC'));
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.