¿Puede wp_query devolver mensajes meta en una sola solicitud?

22

Me gustaría crear un wp_query que devuelva mensajes meta dentro de la postsmatriz.

$args = array (
    'post_type' => 'page',
    'meta_key' => 'someMetaKeyName',
);

// The Query
$query = new WP_Query( $args );

Esto devuelve algo como:

ingrese la descripción de la imagen aquí

Como puede ver, las publicaciones no tienen metadatos, ¿es posible incluir también los metadatos en la matriz devuelta?

PD: No quiero wp_queries adicionales por razones de rendimiento.

YemSalat
fuente
2
El estándar WP_Query no devuelve metadatos de publicaciones. Las únicas opciones que tiene son: 1) ejecutar get_post_metaen teclas individuales, 2) ejecutar get_post_custompara obtener todos los campos personalizados de una publicación en una sola toma, o 3) crear su propia consulta utilizando la clase $ wpdb ( get_results()) para construir su propio objeto de retorno . ($ clase de documentación wpdb : codex.wordpress.org/Class_Reference/wpdb )
BODA82

Respuestas:

20

Por defecto, WP_Querydevuelve los WP_Postobjetos estándar para las publicaciones que se consultan. Creo que con una reescritura inteligente y el uso de los filtros proporcionados WP_Query, puede agregar objetos a la WP_Postmatriz de objetos devueltos .

¿Será esto eficaz? En mi opinión, perjudicará más el rendimiento ya que necesitará unir resultados en su consulta ya que los campos personalizados no se guardan en la wp_poststabla, sino en la wp_postmetatabla

La recuperación de la meta meta es realmente rápida y no requiere ninguna instancia adicional de WP_Query. Simplemente puede llamar al campo personalizado con get_post_meta(). WordPress fue muy atento cuando se introdujeron los campos personalizados. Agregaron un caché para almacenarlos en caché, por lo que si está consultando 1 o 100 campos personalizados, está accediendo a la base de datos una vez, súper rápido. Para una prueba completa y una explicación, vea esta publicación que hice recientemente sobre este tema.

En mi opinión, la llamada adicional a la base de datos y el tiempo real empleado valen la pena y son más rápidos que la reescritura WP_Querypara incluir campos personalizados en el objeto de publicación estándar devuelto por$posts

Pieter Goosen
fuente
Bien, gracias, elegiré este como aceptado, pero para ser honesto, es una molestia llamar get_post_meta()a cada publicación ... Preferiría que hubiera una manera de almacenar datos adicionales directamente en la wp_poststabla o en un tabla relacionada que no es tan mental como wp_postsmetaes.
YemSalat
Bueno, para ser honesto, ya sea llamando get_post_meta()o como un objeto de publicación, deberá llamarlo en cada publicación. Es lo mismo con las etiquetas de plantilla como the_content(), tienes que llamarlo en cada publicación.
Pieter Goosen
2
Esto significa que si tiene que mostrar 120 publicaciones, ¿tendrá 120 consultas adicionales en su página?
chifliiiii
Todos los postdatos se guardan en una memoria caché, por lo que no tendrá consultas adicionales cuando llame a meta post
Pieter Goosen el
Tienes razón. Me refería a post_thumbnails pero recientemente encontré update_post_thumbnail_cache ($ the_query). Gracias de todos modos por la aclaración
chifliiiii
4

Esta pregunta tiene más de 1 año, pero tengo el mismo problema, y ​​aquí está la función que agregará cada meta_value y meta_key al objeto $ wp_query,

en lugar de consultar cada meta del post en el ciclo while, esta función hará un ejemplo de consulta adicional:

"SELECT meta_key, meta_value, post_id FROM $ wpdb-> postmeta DONDE post_id IN (1,2,3,4,5 ...)"

donde (1, 2, 3, 4, 5 ...) se busca ID de publicación de $ wp_query

if(!function_exists('add_query_meta')) {
  function add_query_meta($wp_query = "") {

      //return In case if wp_query is empty or postmeta already exist
      if( (empty($wp_query)) || (!empty($wp_query) && !empty($wp_query->posts) && isset($wp_query->posts[0]->postmeta)) ) { return $wp_query; }

      $sql = $postmeta = '';
      $post_ids = array();
      $post_ids = wp_list_pluck( $wp_query->posts, 'ID' );
      if(!empty($post_ids)) {
        global $wpdb;
        $post_ids = implode(',', $post_ids);
        $sql = "SELECT meta_key, meta_value, post_id FROM $wpdb->postmeta WHERE post_id IN ($post_ids)";
        $postmeta = $wpdb->get_results($sql, OBJECT);
        if(!empty($postmeta)) {
          foreach($wp_query->posts as $pKey => $pVal) {
            $wp_query->posts[$pKey]->postmeta = new StdClass();
            foreach($postmeta as $mKey => $mVal) {
              if($postmeta[$mKey]->post_id == $wp_query->posts[$pKey]->ID) {
                $newmeta[$mKey] = new stdClass();
                $newmeta[$mKey]->meta_key = $postmeta[$mKey]->meta_key;
                $newmeta[$mKey]->meta_value = maybe_unserialize($postmeta[$mKey]->meta_value);
                $wp_query->posts[$pKey]->postmeta = (object) array_merge((array) $wp_query->posts[$pKey]->postmeta, (array) $newmeta);
                unset($newmeta);
              }
            }
          }
        }
        unset($post_ids); unset($sql); unset($postmeta);
      }
      return $wp_query;
  }
}

"Postmeta" adicional se escribirá en cada $ wp_query-> posts [$ i]

$wp_query->posts[0]->postmeta

Ejemplo con 'someMetaKeyName' no olvide poner

add_query_meta() a su tema functin.php

$args = array (
    'post_type' => 'page',
    'meta_key' => 'someMetaKeyName',
);

// The Query
$query = new WP_Query( $args );
if($wp_query->have_posts()) {
  $wp_query = add_query_meta($wp_query);
    $i = 0;
    while($wp_query->have_posts()) {
      $wp_query->the_post();
      $post_id = get_the_id();

      //Get $someMetaKeyName in current post
      foreach($wp_query->posts[$i]->postmeta as $k => $v) {
        switch($v->meta_key) {
          case('someMetaKeyName') : {
            $someMetaKeyName = $v->meta_value;
            break;
          }
        }
      }

      //Your Code here
      //Example 
      echo isset($someMetaKeyName) ? '<h3>'.$someMetaKeyName.'</h3>' : '';


      $i++;
    }
}
Jonny
fuente
Amo esta solución
Armstrongest
3

Recientemente tuve un problema similar, necesitaba obtener 7 piezas de metadatos de un tipo de publicación personalizado, pero también necesitaba obtener la publicación basada en una pieza de metadatos.

Así que creé la siguiente declaración SQL, la uso a menudo. Esperemos que ayude a alguien más. Trataré de explicarlo lo mejor que pueda.

        global $wpdb;
        $pt = 'clients';
        $mk = 'trainerid';
        $mv = $pid;
        $mk1 = 'email';
        $mk2 = 'phone';
        $mk3 = 'gender';
        $mk4 = 'dob';
        $mk5 = 'photo';
        $mk6 = 'registrationts';
        $mk7 = 'activationts';
        $ord = 'p.post_name ASC';

        $sql = "
        SELECT p.ID, p.post_title AS fullname, pm1.meta_value AS email, pm2.meta_value AS phone, pm3.meta_value AS gender, pm4.meta_value AS dob, pm5.meta_value AS photo, pm6.meta_value AS regts, pm7.meta_value AS actemailts
        FROM {$wpdb->posts} p
            LEFT JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID
            AND pm.meta_key = '{$mk}'
            LEFT JOIN {$wpdb->postmeta} pm1 ON pm1.post_id = p.ID
            AND pm1.meta_key = '{$mk1}'
            LEFT JOIN {$wpdb->postmeta} pm2 ON pm2.post_id = p.ID
            AND pm2.meta_key = '{$mk2}'
            LEFT JOIN {$wpdb->postmeta} pm3 ON pm3.post_id = p.ID
            AND pm3.meta_key = '{$mk3}'
            LEFT JOIN {$wpdb->postmeta} pm4 ON pm4.post_id = p.ID
            AND pm4.meta_key = '{$mk4}'
            LEFT JOIN {$wpdb->postmeta} pm5 ON pm5.post_id = p.ID
            AND pm5.meta_key = '{$mk5}'
            LEFT JOIN {$wpdb->postmeta} pm6 ON pm6.post_id = p.ID
            AND pm6.meta_key = '{$mk6}'
            LEFT JOIN {$wpdb->postmeta} pm7 ON pm7.post_id = p.ID
            AND pm7.meta_key = '{$mk7}'
            WHERE pm.meta_value = '{$mv}'
            AND p.post_type = '{$pt}'
            AND p.post_status NOT IN ('draft','auto-draft')
            ORDER BY {$ord}
        ";

        $clients = $wpdb->get_results( $wpdb->prepare( $sql ), OBJECT );

Primero obtengo las funciones de la base de datos de WordPress con $ wpdb global. Luego configuré el posttipo con $ pt. Para obtener la publicación correcta que coincida con un valor específico en post_meta, configuro $ mk (meta_key)

Luego configuro el $ mv (meta_value) var. (en este caso, el metavalor coincide con un postid)

$ mk1- $ mk7 son las meta_keys que quiero de cada publicación. (Tomaré los valores en la instrucción select)

También hago el 'ordenar por' una var, estableciendo $ ord

La declaración de selección es la siguiente: selecciono el ID de la publicación y el post_title de POST o 'p'.

Luego selecciono todos los metadatos que necesito seleccionándolos con pm1. -> pm.7 y agarrando el meta_valor y renombrándolos (AS) para que sea más legible al recuperar los datos de mi objeto.

Creo una IZQUIERDA ÚNICA para los metadatos que necesito para que coincidan con la publicación. (pm)

Creo 7 combinaciones de izquierda para cada uno de los metadatos que necesito recuperar. (pm1-pm7)

La declaración WHERE se basa en la primera LEFT JOIN (pm) para que sepa que solo necesito las publicaciones donde coinciden los metadatos.

También agrego un 'Y' para el tipo de publicación y para los post_statuses que no son borradores. (solo publicaciones publicadas)

Finalmente agrego la cláusula 'ordenar por'.

Esto funciona rápido y con los índices integrados en Wordpress, por lo que parece eficiente.

No sé si algo es mejor que esto, pero si lo es, me encantaría usarlo.

Espero que esto ayude.

Marcus

Marcus
fuente
Gracias, esta publicación es muy útil. Creé una vista con todos los metacampos que necesito y ahora es muy rápido y fácil obtener los datos que quiero
Liko
0

Hey, por favor prueba este, creo que funciona bien.

$args = array(
            'post_type' => 'page',
            'meta_key' => 'someMetaKeyName',
            'meta_query' => array(
                array(
                        'key' => 'someMetaKeyName',
                        'type' => 'CHAR',
                   ),
                ),
        );

    $query = new WP_Query( $args );
Amit Mishra
fuente
¿Cuál es la razón por la que usaste meta_keyy meta_query[]['key']también?
kaiser
1
No, esto no funciona y recupera la variedad de publicaciones sin meta asociados con ellas.
YemSalat
3
meta_keyy / o meta_queryno modifique el tipo de resultados devueltos, solo la consulta misma.
BODA82