WP_Query en WordPress: qué es y cómo se usa (Parte 1)

WP_Query es la clase de WordPress encargada de construir y ejecutar consultas personalizadas sobre la base de datos del sitio web. Gracias a ella, podemos seleccionar exactamente qué contenido queremos mostrar, aplicando filtros, ordenaciones y condiciones específicas según las necesidades de cada proyecto.

Esta clase no solo permite trabajar con entradas y páginas, sino también con Custom Post Types, taxonomías, imágenes adjuntas o campos personalizados, convirtiéndose en una herramienta fundamental dentro del desarrollo avanzado en WordPress.

WP_Query en WordPress es una de las herramientas más importantes para realizar consultas personalizadas de contenido.

Gracias a WP_Query podemos recuperar:

  • entradas
  • páginas
  • Custom Post Types
  • imágenes
  • usuarios
  • contenido filtrado por categorías, etiquetas o taxonomías
  • resultados ordenados y paginados

La clase funciona mediante un conjunto de parámetros que definen qué contenido queremos obtener y cómo queremos mostrarlo.

  • mostrar las últimas entradas
  • obtener publicaciones de un autor concreto
  • filtrar contenido por categorías
  • crear consultas avanzadas con campos personalizados (ACF)
  • construir sliders, galerías o listados personalizados

Ejemplo básico:


   $args = [
       'post_type' => 'post'
   ];
   $query = new WP_Query( $args );

En este ejemplo, WP_Query realiza una consulta para obtener entradas del tipo post.

WP_Query es una de las clases más importantes de WordPress porque permite crear consultas totalmente personalizadas y controlar cómo se recupera y muestra el contenido del sitio web.

Una vez tengamos instalada una versión limpia de WordPress, activaremos el tema Twenty Twelve. Por comodidad, podemos eliminar el resto de temas que vienen instalados por defecto.

Durante este curso realizaremos numerosas prácticas relacionadas con WP_Query, por lo que necesitaremos contenido de prueba sobre el que trabajar. Ese contenido está disponible en el siguiente archivo XML:

Al abrir la URL veremos el código de un archivo. Debemos guardar ese contenido en un fichero con extensión .xml y el nombre que prefiramos.

Este archivo contiene entradas, páginas, categorías, etiquetas, imágenes y distintos tipos de contenido que utilizaremos a lo largo de las prácticas del curso.

Una vez tengamos preparado el archivo XML, lo importaremos en nuestra instalación de WordPress desde:

Herramientas -> Importar -> Ejecutar el importador

Tras completar la importación, ya tendremos suficiente contenido de prueba para comenzar a trabajar con WP_Query.

Ahora abriremos nuestro proyecto de WordPress en el editor de código que utilicemos habitualmente. En mi caso trabajaré con Visual Studio Code.

En la raíz de nuestro tema y en la carpeta ‘page-templates‘ creamos el fichero llamado:

page-wp-query.php

A continuación, copiamos todo el contenido del fichero ‘full-width.php‘ y lo pegamos en el que acabos de crear.

Como vamos a trabajar con una plantilla personalizada de WordPress, debemos modificar la cabecera del archivo. Eliminamos la cabecera original y añadimos una nueva cabecera de plantilla.

Después eliminaremos el Loop de WordPress y, temporalmente, añadiremos un título sencillo para comprobar que la plantilla funciona correctamente.

Finalmente, creamos una nueva página desde el panel de administración con el título: Curso WP_Query.       

y le asignamos la plantilla personalizada que acabamos de crear.

La página que acabamos de crear la añadiremos al ‘Menú Principal‘ para poder acceder a ella fácilmente desde la página de inicio del sitio web.

A continuación, abrimos el fichero ‘page-wp-query.php‘ y colocamos el siguiente código:


   <?php
   /**
    * Template Name: Curso Wp Query
   */

   get_header(); ?>
      <div id="primary" class="site-content">
         <div id="content" role="main">
			
	    <?php if ( have_posts() ) : ?>
               <?php while ( have_posts() ) : the_post(); ?>
                  <h2><?php the_title(); ?></h2>
                     <?php the_content(); ?>
               <?php endwhile; ?>
            <?php endif; ?>

	 </div><!-- #content -->
      </div><!-- #primary -->

   <?php get_footer(); ?>

Antes de continuar, vamos a crear un nuevo usuario. Para ello nos dirigimos a:
Usuarios → Añadir nuevo

Rellenamos los siguientes campos:

  • Nombre de usuario: PepitPerez
  • Correo electrónico: pepitoperez@pepitoperez.com
  • Nombre: Pepito
  • Apellidos: Pérez
  • Perfil: Autor

Nos dirigimos al apartado ‘Entradas‘ y cambiamos el autor de las siguientes publicaciones por Pepito Pérez:

  • Hello World
  • Block: Image
  • Block: Button

Más adelante utilizaremos este autor en distintos ejemplos de consultas con WP_Query.

Dejemos el fichero ‘page-wp-query.php‘ así:


   <?php
   /**
    * Template Name: Curso Wp Query
    *
    */

   get_header(); ?>

	<div id="primary" class="site-content">
           <div id="content" role="main">
              <article>
                 <header class="entry-header">
                    <div><?php the_title(); ?></div>
                 </header>
                 <div class="entry-content">

     
                 </div>
              </article>
	   </div><!-- #content -->
	</div><!-- #primary -->

   <?php get_footer(); ?>

Esta será la plantilla que utilizaremos para todos los ejercicios y ejemplos que veremos a lo largo de este curso.

Dentro del contenedor ‘entry-content‘ iremos añadiendo todas las prácticas relacionadas con WP_Query.


   <div class="entry-content">

      <?php
         // The Query
         $args = [
           'post_type' => 'post',
         ];

         $the_query = new WP_Query( $args );

         // The Loop
         if ( $the_query->have_posts() ) :
           echo '<ul>';
           while ( $the_query->have_posts() ) :

               $the_query->the_post();

               echo '<li>' . get_the_title() . '</li>';

           endwhile;
           echo '</ul>';
         endif;

         wp_reset_postdata();

      ?>

      <?php
         unset( $args );
         unset( $the_query );
      ?>

      <?php the_content(); ?>

   </div><!-- .entry-content -->

Este código crea una consulta personalizada utilizando la clase WP_Query de WordPress para obtener y mostrar un listado de entradas del sitio web.

En primer lugar, definimos un array de argumentos llamado $args. Dentro de este array indicamos que queremos recuperar publicaciones del tipo post, es decir, las entradas normales de WordPress.

A continuación, creamos una nueva instancia de la clase WP_Query y le pasamos los argumentos definidos anteriormente.

Con esto, WordPress ejecuta una consulta personalizada sobre la base de datos y obtiene las entradas correspondientes.

Después utilizamos un Loop personalizado para recorrer los resultados obtenidos por la consulta.

La función have_posts() comprueba si la consulta contiene publicaciones.

Si existen resultados, abrimos una lista HTML y comenzamos a recorrer cada entrada mediante un bucle while.

Dentro del Loop utilizamos:

Este método prepara internamente cada publicación para que podamos utilizar funciones propias de WordPress como:

En este ejemplo únicamente mostramos el título de cada entrada mediante:

Finalmente utilizamos:

para restaurar los datos originales de la consulta principal de WordPress y evitar posibles conflictos con otros elementos de la página.

Al final del ejemplo eliminamos las variables $args y $the_query utilizando unset(). Aunque no es obligatorio, puede ayudar a mantener el código más limpio y liberar memoria una vez finalizada la consulta.

Los parámetros de autor en WP_Query nos permiten filtrar y recuperar contenido publicado por uno o varios usuarios concretos de WordPress.

Gracias a estos parámetros podemos realizar consultas personalizadas para:

  • mostrar entradas de un autor específico
  • excluir publicaciones de determinados usuarios
  • crear páginas de autor personalizadas
  • generar listados filtrados por usuario

Los parámetros de autor trabajan utilizando:

  • el ID del usuario
  • el nombre de usuario (user_nicename)
  • o listas de autores

Algunos de los parámetros más utilizados son: author, author_name, author__in, author__not_in.

Cuando utilizamos parámetros relacionados con author en WP_Query, normalmente estaremos filtrando el contenido mediante el identificador único del usuario dentro de WordPress, es decir, su ID.

A continuación veremos algunos de los casos más utilizados y prácticos a la hora de trabajar con consultas filtradas por autor.


   $args = [
       'post_type' => 'post',
       'posts_per_page' => 10,
       'author' => 5,
   ];

   $the_query = new WP_Query( $args );

En este ejemplo:

  • obtiene entradas del tipo post
  • limita los resultados a 10 publicaciones
  • se filtra únicamente las pertenecientes al autor con ID 5.

Sean los autores con ID 1, 3 y 5.

Como a priori desconocemos el número total de entradas pertenecientes a estos tres autores, añadiremos paginación a nuestra consulta para dividir los resultados en varias páginas.


      <?php

          $paged = get_query_var( 'paged' ) ?: 1;
          
          // The Query
          $args = [
              'post_type' => 'post',
              'posts_per_page' => 10,
              'author__in' => [ 1, 3, 5 ],
              'orderby' => 'date',
              'order' => 'DESC',
          ];

          // Nueva consulta
          $the_query = new WP_Query( $args );

          // The Loop
          if ( $the_query->have_posts() ) :
              echo '<ul>';

              while ( $the_query->have_posts() ) :
                  $the_query->the_post();

                  echo '<li>' . get_the_title() . '</li>';

              endwhile;

              echo '</ul>';

              // Paginación
              echo paginate_links( [
                  'total'   => $the_query->max_num_pages,
                  'current' => $paged,
              ] );

          endif;

          wp_reset_postdata();

      ?>


   $args = [
      'post_type' => 'post',
      'posts_per_page' => 10,
      'author__in' => [ 1, 3, 5 ],
      'orderby' => 'date',
      'order' => 'DESC',
   ];

En el ejemplo;

  • obtiene entradas del tipo post
  • limita el resultado a 10 publicaciones
  • filtra por varios autores
  • ordena las entradas desde las más recientes hasta las más antiguas.

   $args = [
       'post_type' => 'post',
       'posts_per_page' => 5,
       'paged' => $paged,
       'author__not_in' => [ 3, 5 ],
   ];

Si contamos las entradas obtenidas en la consulta anterior, veremos que el total es de 37 publicaciones. Más adelante, cuando mostremos únicamente las entradas pertenecientes a los autores con ID 3 y 5, comprobaremos que la suma total de ambas coincide exactamente con el número de publicaciones existentes.

En muchas ocasiones necesitaremos mostrar únicamente las publicaciones pertenecientes a determinados autores. Para ello,WP_Query dispone de parámetros específicos que permiten filtrar el contenido utilizando los identificadores de usuario de WordPress.


   $args = [
      post_type' => 'post',
      'posts_per_page' => 5,
      'paged' => $paged,
      'author__in' => [ 3, 5 ],
   ];

Además del identificador numérico del usuario, WP_Query también permite filtrar publicaciones utilizando el alias del autor. Internamente, WordPress realiza este filtrado mediante el user_nicename del usuario.

Este tipo de consulta puede resultar útil cuando trabajamos con páginas de autor personalizadas o estructuras donde no queremos depender directamente de IDs numéricos


   $args = [
      'post_type' => 'post',
      'posts_per_page' => 5,
      'paged' => $paged,
      'author_name' => 'pepitoperez',
   ];

En este ejemplo:

  • filtramos las entradas utilizando el alias del autor
  • mostramos 5 publicaciones por página .

Son las tres entradas que asignamos al autor Pepito Pérez cuando lo creamos.

Este tipo de consultas es muy utilizado en zonas privadas, paneles personalizados o plataformas donde cada usuario necesita visualizar únicamente su propio contenido.

Gracias a get_current_user_id(), podemos obtener automáticamente el identificador del usuario actualmente autenticado en WordPress y utilizarlo directamente dentro de WP_Query.

Para que esta consulta muestre resultados correctamente, primero debemos asignar algunas entradas al usuario fransanto, ya que actualmente no dispone de publicaciones asociadas.

Nos dirigimos al apartado Entradas y cambiamos el autor de las siguientes publicaciones por fransanto:

  • Block: Cover
  • Block: Gallery
  • Block: Columns
  • Block: Quote

Ahora filtremos.


   $args = [
      'post_type' => 'post',
      'posts_per_page' => 5,
      'paged' => $paged,
      'author' => get_current_user_id(),
     ];

Puedes ampliar conocimientos visitando:

Las categorías en WordPress son una taxonomía jerárquica utilizada para organizar y clasificar el contenido del sitio web.

Gracias a ellas podemos agrupar publicaciones relacionadas bajo una misma temática, facilitando tanto la navegación de los usuarios como la organización interna del contenido.

Las categorías permiten:

  • estructurar entradas por temas
  • mejorar la experiencia de navegación
  • facilitar la búsqueda de contenido
  • crear archivos organizados automáticamente
  • y realizar consultas personalizadas mediante WP_Query

Al tratarse de una taxonomía jerárquica, una categoría puede contener subcategorías, permitiendo construir estructuras de contenido más complejas y organizadas.

Cuando hablamos de los parámetros de una categoría nos estamos refiriendo a: nombre, slug, categoría superior y descripción.

También tenemos disponible el identificador de la categoría. Si abrimos cualquiera de ellas para editarla, podremos comprobar que su ID aparece directamente en la URL de WordPress.

http://query.local/wp-admin/term.php?taxonomy=category&tag_ID=5&post_type…

En este caso, si identificador es 5 : tag_ID=5

También tenemos el concepto de categoría hija. Esto se consigue asignando una Categoría superior al crear o editar una categoría, tal como podemos ver en el panel de administración de WordPress.

Dentro del listado de categorías del administrador, las categorías hijas aparecen precedidas por un guión delante de su nombre, indicando visualmente su dependencia respecto a la categoría superior.

Ahora que conocemos cómo funcionan las categorías en WordPress, y sabiendo que una entrada puede pertenecer a ninguna, una o varias categorías, ya podemos empezar a trabajar con los parámetros de categoría en WP_Query.


   $args = [
      'post_type' => 'post',
      'paged' => $paged,
      'cat' => 5,
   ];

Nos devuelve todas las entradas que pertenecen a esa categoría.

Además del identificador numérico de una categoría, WP_Query también permite filtrar publicaciones utilizando su slug.


   $args = [
      'post_type' => 'post',
      'posts_per_page' => 5,
      'paged' => $paged,
      'category_name' => 'template-2',
   ];

El slug es la versión amigable utilizada internamente por WordPress en las URLs y normalmente se genera automáticamente a partir del nombre de la categoría.

Este tipo de consultas suele ser más legible y fácil de mantener que trabajar directamente con IDs numéricos.

En este tipo de consultas, los slugs deben separarse mediante comas y WordPress interpretará la búsqueda utilizando una relación lógica OR, devolviendo las entradas que pertenezcan a cualquiera de las categorías indicadas.


   $args = [
      'post_type' => 'post',
      'posts_per_page' => 5,
      'paged' => $paged,
      'category_name' => 'block, template-2',
   ];

Como puedes observar bastará poner las categorías separadas por comas.

En este caso vamos a filtrar excluyendo las dos categorías utilizadas anteriormente, es decir, las categorías con slug block y template-2, cuyos identificadores dentro de WordPress son 7 y 52 respectivamente.


   $args = [
      'post_type' => 'post',
      'posts_per_page' => 5,
      'paged' => $paged,
      'category__not_in' => [ 7, 52 ],
   ];

Como puedes observar, bastará con indicar las categorías separadas mediante comas y encerradas entre corchetes.

El parámetro category__not_in es muy utilizado para excluir contenido concreto de consultas personalizadas, permitiendo construir listados mucho más precisos y controlados.

Como desconocemos a priori si existen entradas que pertenezcan simultáneamente a varias categorías, vamos a asignar manualmente las categorías 7 Y 52 a las tres primeras publicaciones que aparecen en el listado de entradas.

Estas tres publicaciones, al menos en mi instalación de WordPress sin tener en cuenta la entrada programada, son:

  • Hello World!
  • WP 6.1 Font size scale
  • WP 6.1 spacing presets

En este caso, al menos en mi instalación de WordPress:

  • La categoría con ID 7 corresponde a Block
  • La categoría con ID 52 corresponde a Template

   $args = [
      'post_type' => 'post',
      'posts_per_page'=> 5,
      'paged' => $paged,
      'category__and' => [ 7, 52 ],
   ];

WordPress interpreta una relación lógica AND, por lo que únicamente devolverá publicaciones pertenecientes a ambas categorías al mismo tiempo


   $args = [
      'post_type' => 'post',
      'posts_per_page' => 5,
      'paged' => $paged,
      'category_name' => 'classic+markup',
   ];

category_name usa: slug.

debe de escribirse:

  • sin espacios
  • normalmente en minúsculas.

Cuando filtramos utilizando el parámetro cat, WordPress incluye automáticamente las publicaciones pertenecientes a las categorías hijas de la categoría indicada.

Por ejemplo, si la categoría con ID 49 es hija de la categoría con ID 3, las entradas pertenecientes a ambas categorías aparecerán en los resultados de la consulta.


   $args = [
      'post_type' => 'post',
      'posts_per_page'=> 10,
      'paged' => $paged,
      'cat' => 3,
   ];

Vemos que solo nos aparece un resultado.

La categoría con identificador 3 recibe el nombre de aciform que tiene como categoría hija a sub.

Para comprobar cómo funciona este comportamiento en WordPress, nos dirigiremos a la entrada Hello World! y le asignaremos la categoría hija sub.

Hemos comprobado que efectivamente es así ya que nos aparece la entrada Hello World!.

Puedes ampliar conocimientos visitando:

Las etiquetas en WordPress son una taxonomía utilizada para clasificar y relacionar contenido de una forma mucho más flexible que las categorías.

Mientras que las categorías suelen utilizarse para estructurar el contenido de forma jerárquica, las etiquetas permiten describir aspectos concretos de una publicación mediante palabras clave o términos más específicos.

Gracias a WP_Quey, podemos filtrar publicaciones utilizando:

  • el ID de una etiqueta
  • su slug
  • su nombre
  • varias etiquetas simultáneamente
  • o incluso excluir determinadas etiquetas de una consulta.

A continuación veremos los parámetros más importantes relacionados con etiquetas y cómo utilizarlos dentro de nuestras consultas personalizadas.

El parámetro tag_id permite filtrar publicaciones utilizando el identificador numérico de una etiqueta concreta.

Este tipo de consultas resulta especialmente útil cuando trabajamos directamente con IDs obtenidos desde el panel de administración o desde consultas previas.


   $args = [
      'post_type' => 'post',
      'posts_per_page' => 5,
      'paged' => $paged,
      'tag_id' => 81,
   ];

Además del identificador numérico de una etiqueta, WP_Query también permite filtrar publicaciones utilizando su slug.

El slug es el valor utilizado internamente por WordPress en las URLs amigables y normalmente se genera automáticamente a partir del nombre de la etiqueta.

Este tipo de consultas suele resultar más legible y fácil de mantener que trabajar directamente con identificadores numéricos.

   
   $args = [
      'post_type' => 'post',
      'posts_per_page' => 5,
      'paged' => $paged,
      'tag' => 'comments-2',
   ];

‘tag’ => ‘wordpress,gutenberg’, → varios slugs. Relación OR,

Esto nos devolverá:

  • las entradas que tengan la etiqueta wordpress
  • las entradas que tengan la etiqueta gutenberg
  • las entradas que tengan ambas etiquetas

Como desconocemos a priori si existen entradas que pertenezcan simultáneamente a las dos etiquetas que vamos a utilizar en esta consulta, asignaremos manualmente ambas etiquetas a las entradas Hello Wodld! y Block category: Widgets en WordPress.

Cabe recordar que, aunque al asignar etiquetas desde el panel de administración de WordPress utilizamos su nombre visible, WP_Query trabaja normalmente con el slug de la etiqueta dentro de las consultas.


   $args = [
      'post_type' => 'post',
      'posts_per_page' => 5,
      'paged' => $paged,
      'tag' => 'alignment-2+columns',
   ];

Además de filtrar publicaciones pertenecientes a determinadas etiquetas, WP:Query también permite excluir entradas asociadas a una o varias etiquetas concretas en WordPress.

Este tipo de consultas resulta especialmente útil cuando necesitamos ocultar contenido específico dentro de listados personalizados, páginas destacadas o consultas avanzadas.


  $args = [
     'post_type' => 'post',
     'posts_per_page' => 5,
     'paged' => $paged,
     'tag__not_in' => [ 73, 75 ],
  ];

Además de trabajar con identificadores numéricos o slugs, WP_Query también permite excluir publicaciones utilizando directamente el nombre visible de una etiqueta en WordPress.

Este tipo de consultas suele realizarse mediante tax_query, ofreciendo una mayor flexibilidad a la hora de construir consultas avanzadas basadas en taxonomías.


 $args = [
  'post_type' => 'post'
  'posts_per_page' => 5,
  'paged' => $paged,
  
  'tax_query' => [
   [
    'taxonomy' => 'post_tag',
    'field' => 'name',
    'terms => [ 'alignment', 'Columns' ],
      'operator' => 'NOT IN',
    ],
   ],
  ];

Para comprobar que la consulta funciona correctamente, vamos a asignarle a la entrada WP 6.1 Font size scale la etiqueta alignment en WordPress.

Una vez actualizada la entrada y revisado nuevamente el navegador, podremos observar cómo dicha publicación desaparece automáticamente del listado de resultados.

El tema de las taxonomías lo veremos más adelante con mucho más detalle. Esto simplemente ha sido un pequeño inciso de todo lo que todavía nos queda por estudiar en WordPress.

Puedes ampliar conocimientos visitando:

En WordPress tanto las páginas como las entradas pueden configurarse con distintos niveles de visibilidad, pudiendo dejarlas:

  • públicas
  • privadas
  • o protegidas mediante contraseña.

Vamos a modificar la entrada Helo world!, cambiando su título al español por Hola mundo y actualizaremos su slug por hola-mundo.

Una vez realizados estos cambios, asignaremos una contraseña a dicha entrada para dejarla protegida.

Asignaremos la contraseña croqueta a la entrada Hola mundo y realizaremos el mismo proceso con la entrada Bolck: Image, utilizando en este caso la contraseña brava.

Si intentamos acceder a cualquiera de estas dos publicaciones en WordPress, el sistema nos solicitará introducir la contraseña correspondiente para poder visualizar su contenido.

Además de filtrar publicaciones mediante categorías, etiquetas o taxonomías, WP_Query también permite realizar consultas basadas en el estado de protección de una entrada en WordPress.

Gracias al parámetro has_password, podremos obtener únicamente aquellas publicaciones protegidas mediante contraseña o, por el contrario, excluirlas de nuestros resultados.

   
   $args = [
      'post_type' => 'post',
      'posts_per_page' => 5,
      'paged' => $paged,
      'has_password' => true,
   ];

Nos aparece una publicación más de lo esperado. Esto significa que dentro del fichero .xml que importamos inicialmente existía una entrada protegida mediante contraseña en WordPress.

Si, por el contrario, no queremos que nuestra consulta devuelva publicaciones protegidas, deberemos añadir a los argumentos:

‘has_password => false‘.

De esta forma, WP_Query excluirá automáticamente todas las entradas protegidas mediante contraseña.

Además, también es posible filtrar publicaciones utilizando una contraseña concreta. Para ello, bastará con indicar directamente el valor de dicha contraseña dentro del parámetro:

‘has_password’ => ‘brava’.

En este caso, la consulta devolverá únicamente las publicaciones protegidas con esa contraseña específica.

Puedes ampliar conocimientos visitando:

Salir del blog