Kann ich mit der Funktion pre_get_posts einen Beitrag per Metaschlüssel ausschließen?

24

Ich sehe, viele Leute bevorzugen es, pre_get_postsHaken anstelle von zu verwenden query_posts. Der folgende Code funktioniert und zeigt alle Posts an, die den Metaschlüssel "featured" haben.

function show_featured_posts ( $query ) {
    if ( $query->is_main_query() ) {
       $query->set( 'meta_key', 'featured' );
       $query->set( 'meta_value', 'yes' );
    }
}

add_action( 'pre_get_posts', 'show_featured_posts' );

Aber ich möchte , dass die Beiträge , die ‚haben featured‘ meta_key werden ausgeschlossen von der Hauptabfrage. Gibt es dafür einen einfachen Weg?

Carlisle
quelle

Antworten:

33

Ich sehe, dass viele Leute es vorziehen, den Haken pre_get_posts anstelle von query_posts zu verwenden

Yay!

So pre_get_postsfiltert ein WP_QueryObjekt , das heißt alles , was Sie tun können , über die query_posts()Sie über tun können , $query->set()und $query->get(). Insbesondere können wir das meta_queryAttribut verwenden (siehe Codex ):

$meta_query = array(
                 array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                 ),
);
$query->set('meta_query',$meta_query);

Aber ... dies ersetzt die ursprüngliche 'Meta-Abfrage' (falls vorhanden). Wenn Sie also die ursprüngliche Meta-Abfrage nicht vollständig ersetzen möchten, empfehle ich Folgendes:

//Get original meta query
$meta_query = $query->get('meta_query');

//Add our meta query to the original meta queries
$meta_query[] = array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                );
$query->set('meta_query',$meta_query);

Auf diese Weise fügen wir unsere Meta-Abfrage neben vorhandenen Meta-Abfragen hinzu.

Sie können / sollten nicht festlegen relationEigenschaft $meta_queryzu ANDoder OR(nach Rückkehr Beiträge , die alle zufrieden stellen, oder zumindest eine, Meta - Abfragen).

* Hinweis: Bei dieser Art von Abfrage werden Posts mit dem Metaschlüssel "featured" zurückgegeben, deren Wert jedoch nicht ist yes. Es werden keine Posts berücksichtigt, bei denen der "empfohlene" Metaschlüssel nicht vorhanden ist. Sie werden dies in 3.5 tun können .

Stephen Harris
quelle
Es gibt also keine Möglichkeit zu überprüfen, ob ein meta_key für einen Beitrag existiert oder nicht / leer ist oder nicht? Ich werde 3.5 warten müssen. dann. Danke für deine Antwort.
Carlisle
Ich erstelle einfach eine Meta-Box mit Yesund NoOptionen und 'Nein' wird standardmäßig ausgewählt. Wenn ich einen Beitrag veröffentlichen möchte, werde ich auswählen Yes. Ich möchte jedoch, dass die letzten 5 Beiträge weiterhin angezeigt werden und andere in der Hauptabfrage angezeigt werden. Ich möchte nicht jedes Mal zurückgehen und die Auswahl ändern, damit ich nur die letzten 5 Beiträge ausschließen kann. Ich sehe viele ähnliche Fragen zum Stapelaustausch, und es sollte eine einfache Möglichkeit geben, diese vorgestellten Beiträge zu verwalten. (Ein Weg, der sich nicht auf die allgemeine Leistung auswirkt, nicht viele Abfragen erstellt oder gemischte SQL-Abfragen erfordert)
Carlisle
Übrigens bin ich mir nicht sicher, ob es eine gute Idee ist, einen zusätzlichen meta_key mit Yesoder einen NoWert für alle Posts zu erstellen . Es wäre großartig, solche Beiträge auszuschließen, denen einfach der featuredSchlüssel fehlt .
Carlisle
Diese Funktion ist auf meiner Site nach dem Upgrade auf PHP 7 nur Uncaught Error: [] operator not supported for stringsfehlerhaft ausgefallen, da das Original meta_queryals null zurückkam. Sie können das Problem umgehen, indem Sie auf ein leeres Array zurückgreifen, wenn kein Switching-Out $meta_query = $query->get('meta_query');für vorhanden ist $meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];.
Kevin Nugent
2

Ich möchte meine vorübergehende Lösung für vorgestellte Posts veröffentlichen, falls einige Leute davon Gebrauch machen. Ich benutze pre_get_postshier keinen Haken, aber auch nicht query_posts. Das Problem ist, dass ich mit der Hauptabfrage spielen und eine SQL-Abfrage ausführen muss. Ich würde mich freuen, wenn Experten den Code überprüfen und mir mitteilen könnten, ob er in Ordnung ist und keine Leistungsprobleme verursacht. Es wird auch toll sein, wenn jemand einen besseren Ansatz hat und ihn mit uns teilt.

Abfrage für vorgestellte Beiträge erstellen

<?php 

$featured_query = new WP_query( array(
    'meta_key'       =>'featured', 
    'meta_value'     =>'yes', 
    'posts_per_page' => 5, 
    'no_found_rows'  => true
    )
);

while ($featured_query->have_posts()) : 

    $featured_query->the_post(); 
    //Stuff...

endwhile; 
wp_reset_postdata(); 

?>

Erstellen Sie die Hauptabfrage, schließen Sie die Posts mit dem angegebenen meta_key aus, beschränken Sie den Ausschluss auf die letzten 5 Posts und zeigen Sie alle anderen an.

<?php 

$excludeposts = $wpdb->get_col( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'featured' AND meta_value != '' ORDER BY post_id DESC LIMIT 0, 5" );

$main_query = new WP_Query( array(
    'post__not_in' => $excludeposts, 
    'paged' => $paged 
    ) 
);  

while ($main_query->have_posts()) : 

    $main_query->the_post();
    //Stuff...

endwhile;

?>
Carlisle
quelle
0

Als Antwort auf @Carlisle können Sie die folgenden Schritte ausführen, wenn Sie die letzten 5 als "Hervorgehoben" gekennzeichneten Beiträge ausschließen möchten. Ändern Sie die posts_per_page in die Anzahl der auszuschließenden Beiträge und die meta_query in die Art und Weise, wie Sie die vorgestellte Kategorie bestimmen.

function cmp_exclude_featured_posts($query) {
    $exclude = array();  //Create empty array for post ids to exclude
    if ( $query->is_main_query() ) {
            $featured = get_posts(array(
                'post_type' => 'post',
                'meta_query' => array(
                    array(
                        'key' => 'featured',
                        'value' => '1',
                        'compare' => '==',
                    ),
                ),
                'posts_per_page' => 2
            ));

            foreach($featured as $hide) {
                $exclude[] = $hide->ID;
            }   

            $query->set('post__not_in', $exclude);
        }
}

add_filter( 'pre_get_posts', 'cmp_exclude_featured_posts' );
cpeckens
quelle