O wp_query pode retornar as postagens meta em uma única solicitação?

22

Eu gostaria de criar um wp_query que retornaria posts meta dentro da postsmatriz.

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

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

Isso retorna algo como:

insira a descrição da imagem aqui

Como você pode ver, as postagens não possuem metadados, é possível incluir também os metadados na matriz retornada?

PS: Não quero wp_queries adicionais por motivos de desempenho.

YemSalat
fonte
2
O WP_Query padrão não retorna os metadados das postagens. As únicas opções que você tem são: 1) executar get_post_metaem chaves individuais, 2) executar get_post_custompara obter todos os campos personalizados de uma postagem de uma só vez ou 3) criar sua própria consulta usando a classe $ wpdb ( get_results()) para criar seu próprio objeto de retorno . (documentação da classe $ wpdb: codex.wordpress.org/Class_Reference/wpdb )
BODA82

Respostas:

20

Por padrão, WP_Queryretorna os WP_Postobjetos padrão para as postagens que estão sendo consultadas. Acredito que, com alguma reescrita inteligente e o uso dos filtros fornecidos, WP_Queryvocê pode adicionar objetos à WP_Postmatriz de objetos retornados .

Será este um desempenho? Na minha opinião, isso prejudicará mais o desempenho, pois você precisará associar os resultados na sua consulta, pois os campos personalizados não são salvos na wp_poststabela, mas na wp_postmetatabela

A recuperação da meta meta é realmente rápida e não requer nenhuma instância extra de WP_Query. Você pode simplesmente chamar o campo personalizado com get_post_meta(). O WordPress foi muito atencioso quando os campos personalizados foram introduzidos. Eles adicionaram um cache para armazená-los, portanto, se você estiver consultando 1 ou 100 campos personalizados, estará atingindo o banco de dados uma vez, super rápido. Para um teste e explicação completos, consulte este post que fiz recentemente sobre esse assunto.

Na minha opinião, a chamada extra ao banco de dados e o tempo real gasto valem a pena e são mais rápidos do que reescrever de WP_Queryforma a incluir campos personalizados no objeto de postagem padrão retornado por$posts

Pieter Goosen
fonte
OK, obrigado, eu escolherei este como aceito, mas, para ser honesto, é tão complicado chamar get_post_meta()todas as postagens. Prefiro que haja uma maneira de armazenar dados adicionais diretamente na wp_poststabela ou em um tabela relacionada que não é tão preocupante quanto wp_postsmetaé.
YemSalat
Bem, para ser sincero, seja para chamá get_post_meta()-lo como um objeto de postagem, você precisará chamá-lo em todas as postagens. É o mesmo com as tags de modelo como the_content(), você deve chamá-lo em todas as postagens.
Pieter Goosen
2
Isso significa que, se você tiver que mostrar 120 postagens, terá 120 consultas extras em sua página?
Chifliiiii
Todos os postdata são salvos em um cache, assim você não terá consultas extras quando cal; ling meta pós
Pieter Goosen
Você está certo. Eu estava me referindo a post_thumbnails, mas recentemente encontrei update_post_thumbnail_cache ($ the_query). Obrigado de qualquer maneira para o esclarecimento
chifliiiii
4

Esta pergunta tem mais de um ano, mas eu tenho o mesmo problema, e aqui está a função que adicionará cada meta_value e meta_key ao objeto $ wp_query,

em vez de consultar cada meta postada no loop while, esta função fará um exemplo extra de consulta:

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

em que (1,2,3,4,5 ...) são IDs de postagem consultadas com cuidado 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;
  }
}

Additioanal "postmeta" será gravado em cada $ wp_query-> posts [$ i]

$wp_query->posts[0]->postmeta

Exemplo com 'someMetaKeyName' não se esqueça de colocar

add_query_meta() ao seu 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
fonte
Eu amo essa solução.
Armstrongest
3

Recentemente, tive um problema semelhante, precisava obter 7 partes de metadados de um tipo de postagem personalizado, mas também precisava obter a postagem com base em uma parte de metadados.

Então, eu criei a seguinte instrução SQL, eu a uso frequentemente. Espero que ajude alguém. Vou tentar explicar da melhor maneira possível.

        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 );

Primeiro, recebo as funções do banco de dados wordpress com o global $ wpdb. Depois, defino o posttype com $ pt. Para obter a postagem correta que corresponda a um valor específico em post_meta, defino o $ mk (meta_key)

Então eu defino a var $ mv (meta_value). (nesse caso, o valor meta corresponde a um postid)

$ mk1- $ mk7 são as meta_keys que eu quero de cada post. (Vou pegar os valores na instrução select)

Também faço o 'order by' a var, definindo $ ord

A instrução select é a seguinte: seleciono o ID da postagem e o post_title no POST ou 'p'.

Depois, seleciono todos os metadados necessários para selecioná-los com pm1. -> pm.7 e pegando o meta_value e renomeando-os (AS) para ficar mais legível ao recuperar os dados do meu objeto.

Eu crio um JOIN ESQUERDO para os metadados que preciso corresponder à postagem. (PM)

Eu crio 7 junções esquerdas para cada um dos metadados que preciso recuperar. (pm1-pm7)

A instrução WHERE é baseada no primeiro LEFT JOIN (pm), para que saiba que eu preciso apenas das postagens onde os metadados correspondem.

Também adiciono um 'AND' para o tipo de postagem e para os post_statuses que não são rascunhos. (apenas postagens publicadas)

Finalmente, adiciono a cláusula 'order by'.

Isso funciona rápido e com os índices internos do Wordpress, por isso parece eficiente.

Não sei se algo é melhor que isso, mas se for, eu adoraria usá-lo.

Espero que isto ajude.

Marcus

Marcus
fonte
Obrigado, este post é muito útil. Eu criei uma visão com todos os campos de meta que eu preciso e agora é fácil muito rápido e para obter todos os dados que eu quero
Liko
0

Ei, por favor, tente este aqui, acho que funciona bem.

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

    $query = new WP_Query( $args );
Amit Mishra
fonte
Por que você usou meta_keye meta_query[]['key']também?
Kaiser
1
Não, isso não funciona e traz de volta a matriz de postagens sem meta associada a elas.
YemSalat
3
meta_keye / ou meta_querynão modifique o tipo de resultado retornado, apenas a própria consulta.
BOX82