O wp_query pode retornar posts meta em uma única requisição?

17

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

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

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

Isso retorna algo como:

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

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

    
por YemSalat 12.12.2014 / 04:09

4 respostas

17

Por padrão, WP_Query retorna o padrão WP_Post objetos para as postagens que estão sendo consultadas. Eu acredito que com alguma reescrita e uso inteligente dos filtros dados em WP_Query você pode adicionar objetos ao array WP_Post retornado.

Isso será de alto desempenho? Na minha opinião, prejudicarei o desempenho, já que você precisará unir os resultados em sua consulta, pois os campos personalizados não serão salvos na tabela wp_posts , mas na tabela wp_postmeta

A recuperação de post meta é muito rápida e não requer nenhuma instância extra de WP_Query . Você pode simplesmente chamar o campo personalizado com get_post_meta() . Wordpress tem muito pensativo quando os campos personalizados foram introduzidos. Eles adicionaram um cache para armazená-los em cache, 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 esta postagem que fiz recentemente sobre esse assunto

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

    
por Pieter Goosen 12.12.2014 / 05:37
4

Eu tive um problema semelhante recentemente, precisei de 7 metadados de um tipo de postagem personalizado, mas também precisava obter a postagem com base em um metadado.

Então eu criei a seguinte instrução SQL, eu a uso com frequência. Espero que ajude alguém. Vou tentar explicá-lo o melhor que puder.

        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, eu obtenho as funções do banco de dados wordpress com o $ wpdb global. Então eu configurei o posttype com $ pt. Para obter o post correto que corresponde a um valor específico em post_meta, eu defino o $ mk (meta_key)

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

$ mk1- $ mk7 são as meta_keys que eu quero em cada post. (Eu vou pegar os valores na declaração select)

Eu também faço o 'order by' um var, definindo $ ord

A instrução select é a seguinte: Eu seleciono o ID do post e o post_title do POST ou 'p.'

Depois, seleciono todos os metadados que preciso selecioná-los com pm1. - > pm.7 e pegar o meta_value e renomeá-los (AS) para que seja mais legível ao recuperar os dados do meu objeto.

Eu crio um JOIN LEFT para os metadados que preciso corresponder ao post. (pm)

Eu crio 7 left join's para cada um dos metadados que preciso recuperar. (pm1-pm7)

A instrução WHERE baseia-se no primeiro JOGO DE ESQUERDA (pm) para que ele saiba que eu preciso apenas das postagens em que os metadados correspondem.

Eu também adiciono um 'AND' para o tipo de postagem e para os post_statuses que não são rascunhos. (apenas posts publicados)

Por fim, adiciono a cláusula 'order by'.

Isso funciona rápido e com os índices internos do Wordpress, então parece eficiente.

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

Espero que isso ajude.

Marcus

    
por Marcus 14.02.2017 / 02:21
3

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

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

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

em que (1,2,3,4,5 ...) é curiosamente consultado após IDs 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() para o 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++;
    }
}
    
por Jonny 05.05.2016 / 15:10
0

Hey Por favor, tente este, 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 );
    
por Amit Mishra 12.12.2014 / 04:44