Упорядкувати за мета-значенням або датою?


10

Отримане користувацьке поле, яке називається, startDateале воно є лише у кількох подіях. Мені було цікаво, чи він не встановлений для публікації, яку я міг би використовувати post_dateдля створення списку публікацій?

// if meta_key _postmeta.startDate isn't set get the rest by posts.post_date

query_posts(
    array(
        array(
            'posts_per_page' => 10,
            'meta_key' => 'startDate',
            'meta_value' => date('Y-m-d'),
            'meta_compare' => '<',
            'orderby' => 'meta_value',
            'order' => 'ASC'
        ), 
        array(
            'meta_key' => 'post_date',
            'meta_value' => date('Y-m-d'),
            'meta_compare' => '<'
        )
    )
);

є post_date користувацьким полем?
Бейнтернет

Я вважаю, що це поле для WordPress за замовчуванням опубліковане поле, хоча може бути помилковим? У будь-якому випадку я люблю використовувати дату за замовчуванням ...
v3nt

ок, так що це не
метаполе

Виправили свої аргументи запиту, сподіваємось, що це зовсім не перекривило те, що ви ілюстрували, будь ласка, сміливо повертайтеся, якщо потрібно.
t31os

cheers t31os - відредагували його знову, щоб зробити його зрозумілішим. Потрібно, щоб вибрати вміст, старший від СЕЙЧА, використовуючи startDate, а якщо startDate не встановлено, використовуйте дату публікації за замовчуванням post_date.
v3nt

Відповіді:


11

Якщо ви можете пояснити це в SQL, ви можете запитувати його! Є три місця, де ми хочемо змінити запит за замовчуванням:

SELECT wp_posts.*
FROM wp_posts 
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
WHERE 1=1
    AND wp_posts.post_type = 'post'
    AND (wp_posts.post_status = 'publish')
    AND wp_postmeta.meta_key = 'startDate'
    AND CAST(wp_postmeta.meta_value AS CHAR) < '2011-03-23'
GROUP BY wp_posts.ID
ORDER BY wp_postmeta.meta_value DESC
LIMIT 0, 10
  • Приєднання має бути лівим з’єднанням
  • Застереження де
  • Замовлення

Приєднатися і де-пункт додається з допомогою в _get_meta_sql()функції . Вихід фільтрується, тому ми можемо підключити його:

add_filter( 'get_meta_sql', 'wpse12814_get_meta_sql' );
function wpse12814_get_meta_sql( $meta_sql )
{
    // Move the `meta_key` comparison in the join so it can handle posts without this meta_key
    $meta_sql['join'] = " LEFT JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = 'startDate') ";
    $meta_sql['where'] = " AND (wp_postmeta.meta_value IS NULL OR wp_postmeta.meta_value < '" . date('Y-m-d') . "')";
    return $meta_sql;
}

Запит на замовлення фільтрується через posts_orderby:

add_filter( 'posts_orderby', 'wpse12814_posts_orderby' );
function wpse12814_posts_orderby( $orderby )
{
    $orderby = 'COALESCE(wp_postmeta.meta_value, wp_posts.post_date) ASC';
    return $orderby;
}

Це дає нам такий SQL-запит:

SELECT wp_posts.*
FROM wp_posts
LEFT JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id AND wp_postmeta.meta_key = 'startDate')
WHERE 1=1
    AND wp_posts.post_type = 'post'
    AND (wp_posts.post_status = 'publish')
    AND (wp_postmeta.meta_value IS NULL OR wp_postmeta.meta_value < '2011-03-23')
GROUP BY wp_posts.ID
ORDER BY COALESCE(wp_postmeta.meta_value, wp_posts.post_date) ASC
LIMIT 0, 10

Не забудьте зняти фільтри після того, як ви зробили запит, інакше ви зіпсуєте й інші запити. І якщо це можливо , ви не повинні називати query_posts()себе , але змінити основний поштовий запит , який робиться на WordPress при налаштуванні сторінки.


2
Дуже елегантне рішення, я б не думав використовувати подібне COALESCE. Я б просто порадив не приймати префікс 'wp_' за замовчуванням і використовувати замість {$ wpdb-> префікс} ...
goldenapples

@goldenapples: Так, ви могли б узагальнити його, але він вже настільки специфічний для цього запиту (він зіпсує інші запити з мета-частиною), що я вважав, що це не потрібно.
Ян Фабрі

Дякую Яну - це відкривачка для очей! Все ще впораюся з wordpress і цікаво, де це називається на моїй сторінці? І як би я його "відчепив"? тобто // $ theQuery ... тоді <? php if (have_posts ()): while (have_posts ()): the_post (); ?>?
v3nt

@daniel: Ви можете розмістити функції у functions.phpфайлі теми . Тоді безпосередньо перед виконанням запиту ви розміщуєте два add_filter()рядки. Після запиту ви пишете, remove_filter( 'get_meta_sql', 'wpse12814_get_meta_sql' ); remove_filter( 'posts_orderby', 'wpse12814_posts_orderby' );щоб видалити їх знову.
Ян Фабрі

ах - це все має сенс і зараз теж працює! Велике спасибі січень. Це буде корисно ...
v3nt

0

спробуйте щось у порядку:

$postedtime = get_post_meta($post->ID, 'startDate');

if($postedtime != null){
$orderby = $postedtime;

}else{
$orderby = 'date';
}

thankx alex, але не впевнений, як до цього вплутується цикл?
v3nt

До! коли ви query_posts (array ('orderby' => $ orderby))
Алекс Старший

0

Виклик публікацій запиту робить лише один запит, а не два. Отже, ні, ви не можете зробити це, щоб зробити два окремих запити, а потім об'єднати результати.

Пам'ятайте, ви вибираєте тут якийсь набір публікацій, а потім показуєте їх. Цей набір вибирається відразу. Якщо ви хочете отримати два окремі набори публікацій, а потім об'єднати їх, тоді це вам доведеться зробити самостійно з get_posts або подібним.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.