Упорядочить по мета стоимости или дате?

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' => '<'
        )
    )
);
v3nt
источник
post_date - это настраиваемое поле?
Bainternet
я предполагаю, что это опубликованное по умолчанию поле WordPress опубликовано, хотя может быть неправильно? В любом случае, идентификатору нравится использовать дату по умолчанию ...
v3nt
Хорошо, это не мета-поле в таблице сообщений
Bainternet
Исправлены аргументы вашего запроса, надеюсь, что это не изменило то, что вы иллюстрировали, пожалуйста, не стесняйтесь отменить в случае необходимости.
t31os
ура t31os - отредактировал это снова, чтобы сделать это более ясным. Нужно, чтобы он выбирал контент старше NOW, используя 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 ... then <? 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';
}
Алекс Олд
источник
спасибо Алекс, но не уверен, как это включается в цикл?
v3nt
DOH! когда вы запрашиваете (массив ('orderby' => $ orderby))
Алекс Старше
0

Запрос сообщений вызывает только один запрос, а не два. Так что нет, вы не можете сделать два отдельных запроса и затем объединить результаты.

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

эфирное масло
источник