Ordenar por meta valor ou data?

10

Tem um campo personalizado chamado, startDatemas é apenas em alguns eventos. Eu queria saber se não está definido para uma postagem que eu poderia usar post_datepara gerar a lista de postagens?

// 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
fonte
post_date é um campo personalizado?
Bainternet
Presumo que seja o campo publicado padrão do wordpress, embora possa estar errado? De qualquer maneira, a id gostaria de usar a data padrão ... #
313 v3nt
ok, então não é um campo meta a sua na tabela de mensagens
Bainternet
Corrigidos seus argumentos de consulta, espero que isso não tenha distorcido o que você estava ilustrando, sinta-se à vontade para reverter, se necessário.
T31os
Saúde t31os - editei novamente para torná-lo mais claro. É necessário selecionar conteúdo mais antigo que o NOW usando startDate e, se startDate não tiver sido definido, use a data padrão das postagens post_date.
v3nt

Respostas:

11

Se você pode explicá-lo no SQL, pode consultá-lo! Existem três lugares em que queremos alterar a consulta padrão:

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
  • A junção deve ser uma junção esquerda
  • A cláusula where
  • A ordem

A junção e a onde cláusula são adicionados através da _get_meta_sql()função . A saída é filtrada, para que possamos conectá-la:

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;
}

A cláusula de pedido é filtrada por 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;
}

Isso nos fornece a seguinte consulta 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

Lembre-se de soltar os filtros depois de fazer sua consulta, caso contrário você também estragará outras. E, se possível você não deve chamar query_posts()a si mesmo , mas modificar a consulta principal post que é feito por WordPress, enquanto a criação da página.

Jan Fabry
fonte
2
Solução muito elegante, eu não teria pensado em usar o COALESCE assim. Eu só não aconselho assumindo o default 'wp_' prefixo e utilizando {$ wpdb-> prefixo} em vez disso ...
goldenapples
@ goldenapples: Sim, você pode generalizá-lo, mas ele já é tão específico para esta consulta (ele atrapalhará outras consultas com uma meta parte), que achei que isso não era necessário.
Jan Fabry
Jan de graças - que é um abridor de olho! Ainda começando a lidar com o wordpress e querendo saber onde isso é chamado na minha página? E como eu o desengataria? // $ theQuery ... então <? php if (have_posts ()): while (have_posts ()): the_post (); ?>?
v3nt
@daniel: Você pode colocar as funções no functions.phparquivo do seu tema . Logo antes de executar a consulta, você coloca as duas add_filter()linhas. Após a consulta que você escreve remove_filter( 'get_meta_sql', 'wpse12814_get_meta_sql' ); remove_filter( 'posts_orderby', 'wpse12814_posts_orderby' );para removê-los novamente.
Jan Fabry
ah - isso tudo faz sentido agora e funciona também! Muito obrigado Jan. Isso vai ser útil ...
v3nt 24/03
0

tente algo como:

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

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

}else{
$orderby = 'date';
}
Alex Mais velho
fonte
thankx alex, mas não sabe ao certo como isso envolve o loop?
v3nt
doh! quando você query_posts (array ( 'orderby' => $ orderby))
Alex Older
0

Uma chamada de postagens de consulta faz apenas uma consulta, não duas. Portanto, não, você não pode fazer duas consultas separadas e concatenar os resultados.

Lembre-se, você está selecionando um conjunto de postagens aqui e exibindo-as. Esse conjunto é selecionado de uma só vez. Se você deseja obter dois conjuntos separados de postagens e depois mesclá-los, é algo que você terá que fazer com get_posts ou similar.

Otto
fonte