Cerrar
Image Alt

Usando pre_get_posts en vez de query_posts en WordPress

Como ya sabemos hay varias manera de obtener los posts en WordPress:

Vamos a centrarnos en el primero, en el muy utilizado query_posts. Vemos que el codex de WordPress ya nos avisa que algo pasa con query_posts():

“Es preferible utilizar ‘pre_get_posts’ alterando el query principal usando is_main_query”

¿Por qué nos dice esto? Vamos a ver primero cómo funciona query_posts() y entenderemos enseguida el problema.

Cómo funciona query_posts()

Al usar query_posts() estamos diciéndole a WordPress que el trabajo que ha hecho recolectando toda la información del post no vale. Le cambiamos las normas del juego después de haber jugado y le decimos que vuelva a recolectar todos los datos pero en base a unos nuevos criterios que le damos.

Otra vez a recolectar todos los datos, y así cada vez que alguien nos visita (a no ser que hayáis tomado la precaución de cachear los datos con transients o similares). La incidencia en webs con poco tráfico puede ser irrelevante, pero en webs con mucho tráfico sí deberíamos tenerlo en cuenta.

Vamos a verlo en un ejemplo. Supongamos que tenemos un archivo de taxonomías para el que queremos que no salga la categoría 13 y que además nos muestre 8 resultados por página. Si hiciéramos antes del loop:

¿Qué sucedería? WordPress llegaría con todos los datos obtenidos de la base de datos, pero le decimos: vuelve por donde has venido, pero esta vez sin entradas de la categoría 13 y con 8 resultados por página.

¿Cómo le daríamos las instrucciones pertinentes a WordPress antes de que vaya a recoger los datos la primera vez? Con pre_get_posts.

Cómo funciona pre_get_posts

pre_get_posts nos da acceso al objeto $query por referencia (no necesitas declarar globales ni devolver un valor), y se usa de la manera siguiente:

Donde “nombre_funcion” es el nombre de la función que se va a llamar. Esto deberíamos incluirlo en el archivo functions.php de nuestro tema o en un plugin. WordPress necesita crear el query antes de nada para saber qué plantilla (template) va a cargar, por lo que si pones pre_get_posts en una plantilla, como por ejemplo archive.php, será ya demasiado tarde.

Vamos a seguir con el ejemplo anterior. En nuestro archivo functions.php escribiríamos:

Como veis con $query->set establecemos las nuevas condiciones (primero que no incluya la categoría 13 y luego que nos de 8 resultados). Pero, ¿para qué son los condicionales?

Usando pre_get_posts podemos estar afectando más de lo previsto, por eso nos cubrimos las espaldas:

– Este filtro afecta a los queries de las pantallas del administrador. Tenemos por lo tanto que asegurarnos de que nuestra modificación no afecta al administrador de WordPress. De ahí el primer condicional.

– A continuación nos aseguramos de que estamos afectando sólo al query principal, y no a otros queries como los del menú o los de ciertos widgets. Esto lo hacemos comprobando que $query->is_main_query().

– Por último comprobamos que las condiciones son adecuadas para nuestra modificación. Por ejemplo, si quieres que sólo ocurra en la home, el condicional sería $query->is_home(). En nuestro caso queremos asegurarnos de que estamos en la página de archivo de la taxonomía para aplicar el filtro.

Mas ejemplos:

Por ejemplo, si tenemos establecido un número determinado de artículos por página y queremos cambiarlo para ciertas categorías:

Otro ejemplo, queremos que para cierta categoría salgan un cierto número de resultados pero sólo aquellos cuyo valor de un meta value cumpla alguna condición:

Comentarios

  • Es una pena que no funcione en una plantilla. No me gusta tener cosas que sólo afectan a una plantilla en functions.php a base de condicionales. Pero pre_get_posts lo vale! 🙂

    3 agosto, 2013
    contestar
  • Carlos

    todo eso va en el archivo function, pero como lo llamo desde el resto de las plantillas

     

    26 marzo, 2014
    contestar
  • Creo que es entendible, digamos que esto afecta a la forma de mostrar el loop es correcto?, esto afecta a todos los loops en si, el de archive, el del home, search?… o es que solo se utilizaría en el caso de taxonomías o cuando no quieras mostrar entradas de x categoría o alguna otra variable como la cantidad de entradas por página o el orden de presentación?

    14 febrero, 2015
    contestar
  • frank

    Hola Juan, yo he estado por todo google investigando acerca de como usar el pre_get y tengo la misma duda que ha expresado aqui arriba Carlos: segun he visto se coloca la funcion junto con el add_action en functions.php , pero como la llamas desde el punto de la plantilla donde te interesa que se ejecute? gracias

    30 mayo, 2015
    contestar
  • Me vino bien, gracias. No tenía idea de esto hasta que me sirgió un problema con el loop que no mostraba los enlaces de posts_nav_link(). Leí un post en stackexchange me puse a investigar y encontré tu artículo 🙂

    26 julio, 2015
    contestar

Escribe un comentario