Nach Metawert oder Datum bestellen?

10

Ich habe ein benutzerdefiniertes Feld namens, startDateaber es ist nur bei einigen Ereignissen. Ich habe mich gefragt, ob es nicht für einen Beitrag festgelegt ist, mit dem ich post_datedie Liste der Beiträge erstellen kann.

// 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
quelle
Ist post_date ein benutzerdefiniertes Feld?
Bainternet
Ich nehme an, es ist das standardmäßig in WordPress veröffentlichte Feld, obwohl es möglicherweise falsch ist. In
beiden Fällen möchte ich
ok, es ist also kein Meta-Feld in der
Beitragstabelle
Ihre Abfrageargumente wurden korrigiert. Ich hoffe, dass das, was Sie illustriert haben, nicht verzerrt ist. Sie können sie gegebenenfalls zurücksetzen.
t31os
Prost t31os - bearbeitet es erneut, um es klarer zu machen. Benötigt es, um Inhalte, die älter als JETZT sind, mit startDate auszuwählen. Wenn startDate nicht festgelegt wurde, verwenden Sie das Datum post_date der Standardbeiträge.
v3nt

Antworten:

11

Wenn Sie es in SQL erklären können, können Sie es abfragen! 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 _get_meta_sql()Funktion hinzugefügt . Die Ausgabe wird gefiltert, damit wir uns daran anschließen 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 order-Klausel wird gefiltert durch 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;
}

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 nach der Abfrage zu deaktivieren, da Sie sonst auch andere Abfragen durcheinander bringen. Und wenn möglich , sollten Sie sich nicht query_posts()selbst anrufen , sondern die Hauptpost-Abfrage ändern, die WordPress beim Einrichten der Seite ausführt.

Jan Fabry
quelle
2
Sehr elegante Lösung, ich hätte nicht gedacht, COALESCE so zu verwenden. Ich würde nur raten, nicht das Standardpräfix 'wp_' anzunehmen und stattdessen {$ wpdb-> Präfix} zu verwenden ...
goldenapples
@goldenapples: Ja, Sie könnten es verallgemeinern, aber es ist bereits so spezifisch für diese Abfrage (es wird andere Abfragen mit einem Meta-Teil durcheinander bringen), dass ich dachte, dies sei nicht notwendig.
Jan Fabry
Danke Jan - das ist ein Augenöffner! Sie haben immer noch Probleme mit WordPress und fragen sich, wo dies auf meiner Seite heißt? Und wie würde ich es "aushaken"? dh // $ theQuery ... dann <? php if (have_posts ()): while (have_posts ()): the_post (); ?>?
v3nt
@daniel: Sie können die Funktionen in die functions.phpDatei Ihres Themas einfügen . Kurz bevor Sie die Abfrage ausführen, platzieren Sie die beiden add_filter()Zeilen. Nach der Abfrage schreiben Sie, remove_filter( 'get_meta_sql', 'wpse12814_get_meta_sql' ); remove_filter( 'posts_orderby', 'wpse12814_posts_orderby' );um sie wieder zu entfernen.
Jan Fabry
ah - das macht jetzt alles Sinn und funktioniert auch! Vielen Dank Jan. Das wird nützlich sein ...
v3nt
0

Versuchen Sie etwas in der Art von:

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

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

}else{
$orderby = 'date';
}
Alex Older
quelle
danke alx aber nicht sicher, wie dies in die Schleife einbezogen wird?
v3nt
doh! wenn Sie query_posts (Array ('orderby' => $ orderby))
Alex Older
0

Bei einem Aufruf von Abfrageposts 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 Beiträge auswählen und diese dann anzeigen. Dieser Satz wird auf einmal ausgewählt. Wenn Sie zwei separate Sätze von Posts erhalten und diese dann zusammenführen möchten, müssen Sie dies selbst mit get_posts oder ähnlichem tun.

Otto
quelle