¿Puedo excluir una publicación por meta clave usando la función pre_get_posts?

24

Veo que muchas personas prefieren usar pre_get_postsgancho en lugar de query_posts. El siguiente código funciona y muestra todas las publicaciones que tienen metaclave "destacado"

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

Pero quiero que las publicaciones que tienen ' featured' meta_key sean excluidas de la consulta principal. ¿Hay una manera fácil para esto?

Carlisle
fuente

Respuestas:

33

Veo que muchas personas prefieren usar el gancho pre_get_posts en lugar de query_posts

¡Hurra!

Así pre_get_postsfiltra un WP_Queryobjeto que significa cualquier cosa que podría hacer a través de query_posts()usted puede hacer a través de $query->set()y $query->get(). En particular, podemos hacer uso del meta_queryatributo (ver Codex ):

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

Pero ... esto reemplaza la 'meta consulta' original (si tuviera una). Entonces, a menos que desee reemplazar por completo la meta consulta original, sugiero:

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

De esta forma, agregamos nuestra metaconsulta junto con las meta consultas existentes.

Es posible que desee / no establecer la relationpropiedad de $meta_queryto ANDo OR(para devolver publicaciones que satisfagan todas, o al menos una, metaconsultas).

* Nota: Este tipo de consulta devolverá publicaciones con la metaclave 'presentada', pero cuyo valor no es yes. No incluirá publicaciones en las que la metaclave 'destacada' no exista. Podrás hacer esto en 3.5 .

Stephen Harris
fuente
Entonces, ¿no hay forma de verificar si una meta_key para una publicación existe o no / está vacía o no? Tendré que esperar 3.5. luego. Gracias por su respuesta.
Carlisle
Simplemente crearé un meta cuadro con Yesy las Noopciones y 'No' se seleccionarán por defecto. Cuando quiera presentar una publicación, seleccionaré Yes. Sin embargo, quiero que las últimas 5 publicaciones permanezcan destacadas y otras se muestren en la consulta principal. No quiero volver y cambiar la selección cada vez, así que tengo que encontrar una manera de excluir solo las 5 publicaciones más recientes. Veo muchas preguntas similares sobre stackexchange y debería haber una manera fácil de administrar esas publicaciones destacadas. (una forma que no afecta el rendimiento general, no crea muchas consultas o requiere consultas sql mixtas)
Carlisle
Por cierto, no estoy seguro de si es una buena idea crear una meta_key adicional con Yeso Novalor para todas las publicaciones. Sería genial excluir aquellas publicaciones que simplemente carecen de la featuredclave.
Carlisle
Esta función simplemente se rompió en mi sitio después de actualizar a PHP 7 arrojando un Uncaught Error: [] operator not supported for stringserror ya que el original meta_queryvolvía a ser nulo. Se puede conseguir alrededor de él por la caída de nuevo a una matriz vacía si no existe ninguno de conmutación de salida $meta_query = $query->get('meta_query');para $meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];.
Kevin Nugent
2

Quiero publicar mi solución temporal para publicaciones destacadas en caso de que algunas personas puedan utilizarla. No uso el pre_get_postsgancho aquí, pero query_poststampoco. El problema es que tengo que jugar con la consulta principal y ejecutar una consulta SQL. Me encantaría que algún experto pudiera verificar el código y hacerme saber si está bien y no causará problemas de rendimiento. También será genial si alguien tiene un mejor enfoque y lo comparte con nosotros.

Crear consulta de publicaciones destacadas

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

?>

Cree la consulta principal, excluya las publicaciones que tienen la meta_key destacada, limite la exclusión a las 5 publicaciones más recientes y muestre todas las demás.

<?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
fuente
0

En respuesta @Carlisle, si desea excluir las 5 publicaciones recientes marcadas como destacadas, puede hacer lo siguiente. Cambie posts_per_page a cuántos desea excluir y meta_query a cómo está designando la categoría destacada.

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
fuente