Quiero excluir cada publicación con un valor específico de un metacampo personalizado. El problema es que no todas las publicaciones tienen este metacampo.
Mi código se ve así (extracto del ciclo de trabajo):
// WP_Query arguments
$args = array (
'post_parent' => $parentid,
'orderby' => 'menu_order',
'order' => 'ASC',
'post_type' => array( 'page' ),
'meta_query' => array(
array(
'key' => 'hide',
'value' => 1,
'compare' => '!='
)
)
);
No todas las publicaciones usan el campo “ocultar”. Algunas publicaciones devuelven un NULL. ¡¿Entonces creo que el ciclo no funciona por eso?!
¿Es esto correcto? ¿Es necesario que cada publicación tenga un valor para esa clave?
bpy
Otra forma de hacerlo:
// WP_Query arguments
$args = array (
'post_parent' => $parentid,
'orderby' => 'menu_order',
'order' => 'ASC',
'post_type' => array( 'page' ),
'meta_query' => array('0' => array('key' => 'hide', 'value' => '1', 'compare' => 'NOT EXISTS')
)
);
llaves mate
Esta es una publicación anterior, pero para responderla de todos modos. La metaconsulta en esta pregunta solo arrojará resultados de publicaciones que tengan esa metaclave. Para devolver también publicaciones que no tienen esa clave meta, necesita una consulta meta adicional. Ejemplo:
// WP_Query arguments
$args = array (
'post_parent' => $parentid,
'orderby' => 'menu_order',
'order' => 'ASC',
'post_type' => array( 'page' ),
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'hide',
'value' => 1,
'compare' => '!='
),
array(
'key' => 'hide',
'compare' => 'NOT EXISTS'
)
)
);
Tenga en cuenta el uso de “relación” y la segunda metaconsulta que tiene el valor de comparación de ‘NO EXISTE’.
ACTUALIZAR CON CÓMO MANEJO ESTA SITUACIÓN ACTUALMENTE:
Parece que me encuentro con situaciones como esta cada vez más, y he desarrollado un método para manejarlo que da como resultado una consulta SQL mucho más rápida. Cada vez que se guarda una publicación en el tipo de publicación en cuestión, actualizo una lista de ID de publicación que cumplen con mis criterios de consulta y la almaceno en una opción de WP. Luego, cuando se ejecuta mi consulta, obtengo esta lista y la coloco en el parámetro de consulta ‘incluir’ o ‘excluir’ dependiendo de si se trata de una lista blanca o una lista negra.
Esto agrega un poco de código, pero los beneficios aquí son tanto en el rendimiento como en la eliminación de cierta complejidad si tiene otras metaconsultas que también deben ejecutarse. Algunos códigos de ejemplo a continuación para una lista negra, esto también podría adaptarse para una lista blanca.
class Example_Meta_Blacklist
{
public function init()
{
/*
* Trigger whenever post is saved, you could also trigger on save_post_{$post->post_type}
* If you are using Advanced Custom Fields, you may need to use acf/save_post
*/
add_action( 'save_post', [ $this, 'update_my_custom_post_type_blacklist' ] );
/*
* One time use function to create an initial list if needed. Remove if not.
*/
add_action( 'wp', [ $this, 'create_initial_my_custom_post_type_blacklist' ] );
}
/*
* Add or remove post ids from our list whenever the post is saved
*/
public function update_my_custom_post_type_blacklist( $post_id )
{
if ( 'my_custom_post_type' != get_post_type( $post_id ) ) {
return;
}
$my_custom_post_type_blacklist = get_option( 'my_custom_post_type_blacklist', [] );
$key = array_search( $post_id, $my_custom_post_type_blacklist );
$meta_key_in_question = get_post_meta( $post_id, 'meta_key_in_question', true );
if ( ! $meta_key_in_question && $key !== false ) {
unset( $my_custom_post_type_blacklist[ $key ] );
} else if ( $meta_key_in_question && $key === false ) {
$my_custom_post_type_blacklist[] = $post_id;
}
update_option( 'my_custom_post_type_blacklist', $my_custom_post_type_blacklist, true );
}
/*
* When I run into this issue, there are usually already some existing
* posts, so I need to run this code one-time to create my initial list
* This code would be run by visiting your site with ?gocode=myuniquegocode
* at the end of the URL. The function and action hook can then be removed.
*/
public function create_initial_my_custom_post_type_blacklist()
{
if ( ! isset( $_GET['gocode'] ) || 'myuniquegocode' != $_GET['gocode'] ) {
return;
}
$clients = get_posts([
'posts_per_page' => -1,
'post_type' => 'my_custom_post_type',
'post_status' => 'publish',
'fields' => 'ids',
'meta_key' => 'the_meta_key_in_question',
'meta_value' => 'the_meta_value_in_question',
'meta_compare' => '='
]);
update_option( 'my_custom_post_type_blacklist', $clients, true );
}
}
add_action( 'plugins_loaded', [ new Example_Meta_Blacklist, 'init' ] );
Luego, en una consulta de publicaciones:
$my_query = new WP_Query( [
'post_type' => 'my_custom_post_type',
'post_status' => 'publish',
'exclude' => get_option( 'my_custom_post_type_blacklist', [] )
] );
-
Vale la pena señalar que cuanto más complicadas se vuelven estas consultas, más lentas también. Dependiendo de su caso de uso, esto podría tener una diferencia de rendimiento sustancial. Si el rendimiento es un problema, es posible que desee considerar escribir una función que asigne la clave meta a todas las publicaciones en su tipo de publicación para que funcione su consulta original.
– Matt Keys
4 sep 2019 a las 19:04
-
Actualicé esta respuesta con un código que muestra cómo manejo esta situación hoy en día.
– Matt Keys
3 de febrero de 2021 a las 20:46
-
En algunas pruebas en una consulta recientemente, encontré que la consulta en mi respuesta original tomaba 450 ms, mientras que el método más nuevo que agregué solo tomó 25 ms. Estos números específicos variarán según la cantidad de publicaciones que esté consultando y otros factores. Pero creo que la diferencia entre los dos ilustra las implicaciones de rendimiento aquí.
– Matt Keys
02/03/2021 a las 20:35
Intente verificar su declaración SQL haciendo lo siguiente.
$customPosts = new WP_Query($yourArgs);
echo "Last SQL-Query: {$customPosts->request}";
-
he hecho eso Por eso sé que falta el campo en la mayoría de las páginas 🙂
– Cray
07/01/2016 a las 18:50
-
Este es un buen consejo sobre cómo depurar algunos resultados de WP_Query, pero no es una respuesta a esta pregunta.
– Matt Keys
5 sep 2019 a las 19:46
-
Me llevó a mi respuesta, gracias!
– Adam Pearlman
4 de febrero a las 11:11
meta consulta se ve bien. cuál es tu problema actual
– Venkat.R
07/01/2016 a las 18:30
El problema es que si uso meta_query como se ve en el ejemplo anterior, ya no obtengo páginas.
– Cray
07/01/2016 a las 18:32
funciona si eliminas meta_query ?
– Venkat.R
07/01/2016 a las 18:35
Sí. Quiero excluir páginas con este campo. Así que no todas las páginas tienen este campo.
– Cray
07/01/2016 a las 18:38
Prueba así ‘valor’ => ‘1’,
– Venkat.R
07/01/2016 a las 18:40