Czy mogę wykluczyć post za pomocą meta-klucza za pomocą funkcji pre_get_posts?

24

Widzę, że wiele osób woli używać pre_get_postshaczyka zamiast query_posts. Poniższy kod działa i pokazuje wszystkie posty, które mają „polecany” meta klucz

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' );

Chcę jednak, aby posty zawierające featured„meta_key” były wykluczone z głównego zapytania. Czy jest na to łatwy sposób?

Carlisle
źródło

Odpowiedzi:

33

Widzę, że wiele osób woli używać zaczepu pre_get_posts zamiast query_posts

Tak!

Tak pre_get_postsfiltruje WP_Queryobiektu , co oznacza niczego można zrobić poprzez query_posts()można zrobić poprzez $query->set()a $query->get(). W szczególności możemy skorzystać z meta_queryatrybutu (patrz Kodeks ):

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

Ale… to zastępuje oryginalne „meta kwerenda” (jeśli taka miała). Więc jeśli nie chcesz całkowicie zastąpić oryginalnego zapytania meta, sugeruję:

//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);

W ten sposób dodajemy nasze zapytanie do meta obok istniejących zapytań do meta.

Możesz / możesz nie chcieć ustawić relationwłaściwości $meta_queryna ANDlub OR(aby zwracać posty, które spełniają wszystkie, lub przynajmniej jedno, meta-zapytania).

* Uwaga: ten typ zapytania zwróci posty z „polecanym” meta kluczem, ale którego wartość nie jest yes. Nie będzie zawierać postów, w których „polecany” meta klucz nie istnieje. Będziesz mógł to zrobić w 3.5 .

Stephen Harris
źródło
Więc nie ma sposobu, aby sprawdzić, czy meta_klucz do wpisu istnieje, czy nie / jest pusty, czy nie? Będę musiał czekać 3.5. następnie. Dzięki za odpowiedź.
Carlisle,
Ja po prostu utworzyć pole z meta Yesi Noopcje i „nie” będzie domyślnie zaznaczona. Kiedy chcę polecić post, wybiorę Yes. Chcę jednak, aby 5 ostatnich postów pozostało polecanych, a inne będą wyświetlane w głównym zapytaniu. Nie chcę wracać i zmieniać wyboru za każdym razem, więc muszę znaleźć sposób na wykluczenie tylko ostatnich 5 postów. Widzę wiele podobnych pytań na temat stackexchange i powinien istnieć łatwy sposób zarządzania tymi polecanymi postami. (sposób, który nie wpływa na ogólną wydajność, nie tworzy wielu zapytań ani nie wymaga mieszanych zapytań SQL)
Carlisle,
BTW Nie jestem pewien, czy dobrym pomysłem jest utworzenie dodatkowego meta_key z Yeslub Nowartości dla wszystkich postów. Byłoby wspaniale wykluczyć te posty, które po prostu nie mają featuredklucza.
Carlisle,
Ta funkcja właśnie zepsuła się na mojej stronie po aktualizacji do PHP 7, zgłaszając Uncaught Error: [] operator not supported for stringsbłąd, ponieważ oryginał meta_querywracał jako zerowy. Można to obejść przez sięgnięcie do pustej tablicy, jeśli żaden nie istnieje przełączania się $meta_query = $query->get('meta_query');na $meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];.
Kevin Nugent,
2

Chcę opublikować moje tymczasowe rozwiązanie dla polecanych postów na wypadek, gdyby niektóre osoby mogły z niego skorzystać. Nie używam pre_get_poststutaj haczyka, ale też nie query_posts. Problem polega na tym, że muszę grać z głównym zapytaniem i uruchomić kawałek zapytania SQL. Byłbym szczęśliwy, gdyby jakikolwiek ekspert mógł sprawdzić kod i dać mi znać, czy jest w porządku i nie spowoduje żadnych problemów z wydajnością. Będzie również świetnie, jeśli ktoś będzie miał lepsze podejście i podzieli się nim z nami.

Utwórz zapytanie o polecane posty

<?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(); 

?>

Utwórz główne zapytanie, wyklucz posty z poleconym meta_key, ogranicz wykluczenie do 5 najnowszych postów i pokaż wszystkie inne.

<?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
źródło
0

W odpowiedzi na @Carlisle, jeśli chcesz wykluczyć 5 najnowszych postów oznaczonych jako polecane, możesz wykonać następujące czynności. Zmień stronę posts_per_page na liczbę, które chcesz wykluczyć, a meta_query na sposób oznaczania polecanej kategorii.

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
źródło