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


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.