web-dev-qa-db-de.com

Bestellung nach Meta-Wert oder Datum?

Ich habe ein benutzerdefiniertes Feld mit dem Namen startDate erhalten, aber es ist nur bei einigen Ereignissen möglich. Ich habe mich gefragt, ob es nicht für einen Beitrag festgelegt ist, für den ich post_date verwenden kann, um die Beitragsliste zu erstellen.

// 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' => '<'
        )
    )
);
10
v3nt

Wenn Sie es in SQL erklären können, können Sie danach fragen! Es gibt drei Stellen, an denen wir die Standardabfrage ändern möchten:

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
  • Der Join sollte ein linker Join sein
  • Die Where-Klausel
  • Die Bestellung

Der Join und die Where-Klausel werden über die Funktion _get_meta_sql() hinzugefügt. Die Ausgabe wird gefiltert, damit wir sie einbinden können:

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

Die Bestellklausel wird durch posts_orderby gefiltert:

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

Dies gibt uns die folgende SQL-Abfrage:

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

Denken Sie daran, die Filter zu deaktivieren, nachdem Sie Ihre Abfrage durchgeführt haben, da Sie sonst auch andere Abfragen durcheinander bringen. Und wenn möglich sollten Sie query_posts() nicht selbst aufrufen , sondern die Hauptpost-Abfrage ändern, die von WordPress beim Einrichten der Seite ausgeführt wird.

11
Jan Fabry

versuchen Sie etwas in der Art von:

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

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

}else{
$orderby = 'date';
}
0
Alex Older

Bei einem Abfrage-Posts-Aufruf wird nur eine Abfrage ausgeführt, nicht zwei. Nein, Sie können nicht zwei separate Abfragen durchführen und dann die Ergebnisse verketten.

Denken Sie daran, dass Sie hier einige Posts auswählen und dann anzeigen. Dieser Satz wird auf einmal ausgewählt. Wenn Sie zwei separate Sätze von Posts abrufen und dann zusammenführen möchten, müssen Sie dies mit get_posts oder ähnlichem tun.

0
Otto