$GLOBALS['wp_the_query'] versus global $wp_query

14 mar 2016, 10:12:16
Vistas: 30.4K
Votos: 23

¿Cuál es la diferencia entre $GLOBALS['wp_the_query'] y global $wp_query?

¿Por qué preferir uno sobre el otro?

2
Comentarios

¡Diría global $wp_query solo para responder tu pregunta en una línea!

Sumit Sumit
14 mar 2016 10:17:40

¿Cuál es la diferencia?

Nathan Powell Nathan Powell
14 mar 2016 10:23:59
Todas las respuestas a la pregunta 3
6
34

Te has olvidado de uno, $GLOBALS['wp_query']. Para todos los efectos, $GLOBALS['wp_query'] === $wp_query. Sin embargo, $GLOBALS['wp_query'] es mejor para la legibilidad y debería usarse en lugar de $wp_query, PERO, eso sigue siendo una preferencia personal.

Ahora, en un mundo perfecto donde los unicornios gobiernan el mundo, $GLOBALS['wp_the_query'] === $GLOBALS['wp_query'] === $wp_query. Por defecto, esto debería ser cierto. Si miramos dónde se establecen estos globales (wp-settings.php), verás que el objeto de consulta principal se almacena en $GLOBALS['wp_the_query'] y $GLOBALS['wp_query'] es solo una copia duplicada de $GLOBALS['wp_the_query'].

/**
 * Objeto de consulta de WordPress
 * @global WP_Query $wp_the_query
 * @since 2.0.0
 */
$GLOBALS['wp_the_query'] = new WP_Query();
/**
 * Contiene la referencia a @see $wp_the_query
 * Usa este global para las consultas de WordPress
 * @global WP_Query $wp_query
 * @since 1.5.0
 */
$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];

La razón de hacerlo de esta manera es porque WordPress vio la llegada de query_posts en la versión 1.5.

function query_posts($query) {
    $GLOBALS['wp_query'] = new WP_Query();
    return $GLOBALS['wp_query']->query($query);
}

Como puedes ver, query_posts establece el objeto de consulta principal a la consulta personalizada actual que se está ejecutando. Esto rompe la integridad del objeto de consulta principal, lo que te da datos incorrectos, por lo que cualquier cosa que dependa del objeto de consulta principal se rompe debido a datos erróneos.

Una forma de contrarrestar esto fue crear otro global para almacenar el objeto de consulta principal, $GLOBALS['wp_the_query'], que se introdujo en la versión 2.0.0. Este nuevo global contiene el objeto de consulta principal y $GLOBALS['wp_query'] es solo una copia. A través de wp_reset_query(), ahora podíamos restablecer $GLOBALS['wp_query'] al objeto de consulta principal original para restaurar su integridad.

Pero este no es un mundo perfecto, y query_posts es el mismísimo diablo. A pesar de miles de advertencias, la gente sigue usando query_posts. Aparte de romper la consulta principal, vuelve a ejecutar la consulta principal, haciéndola mucho más lenta que una consulta personalizada normal con WP_Query. Mucha gente tampoco restablece la consulta de query_posts con wp_reset_query() cuando termina, lo que hace que query_posts sea aún más malvado.

Como no podemos hacer nada al respecto, y no podemos evitar que los plugins y temas usen query_posts y nunca podemos saber si una consulta de query_posts se restableció con wp_reset_query(), necesitamos una copia más confiable del objeto de consulta principal que sepamos que nos dará datos correctos en un 99.99999% de los casos. Ahí es donde $GLOBALS['wp_the_query'] es útil, ya que ningún código relacionado con WordPress puede cambiar su valor (excepto a través de los filtros y acciones dentro del propio WP_Query).

Prueba rápida, ejecuta lo siguiente:

var_dump( $GLOBALS['wp_the_query'] );
var_dump( $GLOBALS['wp_query'] );

query_posts( 's=crap' );


var_dump( $GLOBALS['wp_the_query'] );
var_dump( $GLOBALS['wp_query'] );

y revisa los resultados. $GLOBALS['wp_the_query'] no cambió, y $GLOBALS['wp_query'] sí. Entonces, ¿cuál es más confiable?

Nota final, $GLOBALS['wp_the_query'] NO es un reemplazo para wp_reset_query(). wp_reset_query() debe usarse siempre con query_posts, y query_posts nunca debería usarse.

PARA CONCLUIR

Si necesitas código confiable que casi nunca falle, usa $GLOBALS['wp_the_query']. Si confías y crees en los códigos de plugins y temas y crees que nadie usa query_posts o lo está usando correctamente, usa $GLOBALS['wp_query'] o $wp_query.

EDICIÓN IMPORTANTE

Después de responder preguntas en este sitio durante un par de años, he visto a muchos usuarios usar $wp_query como una variable local, lo que a su vez también rompe el objeto de consulta principal. Esto aumenta aún más la vulnerabilidad de $wp_query.

Por ejemplo, algunas personas hacen esto:

$wp_query = new WP_Query( $args );

que en esencia es exactamente lo mismo que lo que hace query_posts.

14 mar 2016 11:31:15
Comentarios

query_posts() cambia global $wp_query. global $wp_the_query contiene la referencia a la consulta principal

Evan Mattson Evan Mattson
15 mar 2016 21:06:01

Mi comentario no tenía la intención de ser una corrección, así que disculpas si lo pareció. Solo estaba resumiendo (TL;DR si prefieres) mientras señalaba lo que creo que es uno de los aspectos más significativos de $wp_the_query en relación con el método WP_Query::is_main_query(), que no fue mencionado :D

Evan Mattson Evan Mattson
16 mar 2016 02:37:20

@EvanMattson Disculpas, malinterpreté tu primer comentario ;-). Sí, is_main_query(), que es un envoltorio para WP_Query::is_main_query(), verifica el objeto de consulta actual contra el objeto de consulta principal guardado en $GLOBALS['wp_the_query']. Esto es bastante importante cuando ejecutas acciones pre_get_posts y solo quieres apuntar a la consulta principal ;-)

Pieter Goosen Pieter Goosen
16 mar 2016 06:18:22

¡Respuesta muy bien hecha! @EvanMattson Eso debería haber sido una [edición].

kaiser kaiser
7 abr 2016 00:49:58

¿Podrías incluir una mención a la función is_main_query en la sección *EDIT IMPORTANTE*? Estaba usando pre_get_posts hoy y encontré extremadamente útil usar esa función ya que estaba mirando $wp_query.

Nathan Powell Nathan Powell
18 mar 2017 02:50:17

Solo señalo que global $name y $GLOBALS['name'] son sinónimos. Siempre apuntan al mismo objeto. Entonces, solo hay dos objetos: global $wp_query y global $wp_the_query

Philipp Philipp
3 sept 2021 21:58:34
Mostrar los 1 comentarios restantes
1

La palabra clave global importa la variable al ámbito local, mientras que $GLOBALS simplemente te da acceso a la variable.

Para elaborar, si usas global $wp_the_query; puedes usar $wp_the_query dentro del ámbito local sin tener que usar la palabra global nuevamente. Básicamente, global $wp_the_query puede compararse con $wp_the_query = $GLOBALS['wp_the_query']

EDICIÓN

Leí mal wp_query como wp_the_query, así que mi respuesta no es una respuesta completa a la pregunta, pero aún proporciona información general sobre la diferencia entre global $variable y $GLOBALS['variable']

14 mar 2016 10:27:55
Comentarios

Por favor, envía una [edición] ya que esto realmente no es una respuesta a la pregunta original. Solo para tu información, $GLOBALS['foo'] permite sobrescribir o anular la variable también. Así que es un poco más de lo que describes aquí.

kaiser kaiser
7 abr 2016 00:52:37
0

Básicamente, uno es una copia del otro.

14 mar 2016 10:29:21