Wp_query può restituire meta post in una singola richiesta?


22

Vorrei creare un wp_query che restituirebbe meta post all'interno postsdell'array.

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

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

Questo restituisce qualcosa del tipo:

inserisci qui la descrizione dell'immagine

Come puoi vedere, i post non hanno metadati, è possibile includere anche i metadati nell'array restituito?

PS Non voglio ulteriori wp_queries per motivi di prestazioni.


2
WP_Query standard non restituisce i metadati dei post. Le uniche opzioni che hai sono: 1) eseguire get_post_metasu singole chiavi, 2) eseguire get_post_customper ottenere tutti i campi personalizzati di un post in un colpo solo, o 3) creare la tua query usando la classe $ wpdb ( get_results()) per costruire il tuo oggetto di ritorno . (Documentazione della classe $ wpdb: codex.wordpress.org/Class_Reference/wpdb )
BODA82

Risposte:


20

Per impostazione predefinita, WP_Queryrestituisce gli WP_Postoggetti standard per i post interrogati. Credo che con una riscrittura intelligente e l'uso dei filtri forniti in WP_Queryte sia possibile aggiungere oggetti alla WP_Postmatrice di oggetti restituiti .

Sarà questo performante? A mio avviso, danneggerà maggiormente le prestazioni in quanto sarà necessario unire i risultati alla query poiché i campi personalizzati non vengono salvati nella wp_poststabella, ma nella wp_postmetatabella

Il recupero di meta meta è molto veloce e non richiede alcuna istanza aggiuntiva di WP_Query. Puoi semplicemente chiamare il campo personalizzato conget_post_meta() . WordPress è stato molto premuroso quando sono stati introdotti i campi personalizzati. Hanno aggiunto una cache per memorizzarli nella cache, quindi sia che tu stia interrogando 1 o 100 campi personalizzati, stai colpendo il database una volta, superveloce. Per un test completo e una spiegazione, vedi questo post che ho recentemente fatto su questo argomento.

A mio avviso, la chiamata al database aggiuntivo e il tempo effettivamente trascorso ne valgono la pena e sono più veloci della riscrittura WP_Queryin modo da includere campi personalizzati nell'oggetto postale standard restituito da$posts


OK, grazie, sceglierò questo come accettato, ma a dire il vero è solo una seccatura chiamare get_post_meta()per ogni singolo post. Preferirei che ci fosse un modo per archiviare dati aggiuntivi direttamente nella wp_poststabella o in un tabella correlata che non è tanto simile a quella di una mente wp_postsmeta.
YemSalat,

Bene, a dire il vero, sia che lo si chiami get_post_meta()o come oggetto postale, sarà necessario chiamarlo su ogni post. È lo stesso con tag modello come the_content(), devi chiamarlo su ogni post.
Pieter Goosen,

2
Ciò significa che se devi mostrare 120 post avrai 120 richieste extra nella tua pagina?
Chifliiiii,

Tutti i postdata vengono salvati in una cache, quindi non avrai ulteriori domande quando cal; ling post meta
Pieter Goosen

Hai ragione. Mi riferivo a post_thumbnails ma di recente ho trovato update_post_thumbnail_cache ($ the_query). Grazie comunque per il chiarimento
chifliiiii

4

Questa domanda ha più di 1 anno, ma ho lo stesso problema, ed ecco la funzione che aggiungerà ogni meta_valore e meta_key all'oggetto $ wp_query,

invece di eseguire una query su ogni meta meta in ciclo while, questa funzione farà un esempio di query extra:

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

dove (1,2,3,4,5 ...) viene interrogato in modo corrente ID post da $ 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" aggiuntivo verrà scritto in ogni $ wp_query-> posts [$ i]

$wp_query->posts[0]->postmeta

Esempio con 'someMetaKeyName' non dimenticare di mettere

add_query_meta() al tuo 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++;
    }
}

Adoro questa soluzione.
Armstrongest

3

Recentemente ho avuto un problema simile, avevo bisogno di ottenere 7 pezzi di metadati da un tipo di post personalizzato, ma avevo anche bisogno di ottenere il post basato su un pezzo di metadati.

Quindi ho creato la seguente istruzione SQL, la uso spesso. Spero che possa aiutare qualcun altro. Proverò a spiegarlo nel miglior modo possibile.

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

Per prima cosa ottengo le funzioni del database wordpress con $ wpdb globale. Quindi ho impostato il posttype con $ pt. Per ottenere il post corretto che corrisponde a un valore specifico in post_meta, ho impostato $ mk (meta_key)

Quindi ho impostato $ mv (meta_value) var. (in questo caso il meta valore corrisponde a un postid)

$ mk1- $ mk7 sono i meta_key che desidero da ogni post. (Prenderò i valori nell'istruzione select)

Faccio anche 'ordina per' un var, impostando $ ord

L'istruzione select è la seguente: seleziono l'ID post e il post_title dal POST o 'p.'

Quindi seleziono tutti i metadati di cui ho bisogno selezionandoli con pm1. -> pm.7 e afferrando il meta_value e rinominandoli (AS) in modo che sia più leggibile quando si recuperano i dati dal mio oggetto.

Creo un JOIN SINISTRA per i metadati che devo abbinare al post. (Pm)

Creo 7 join di sinistra per ciascuno dei metadati che devo recuperare. (PM1-PM7)

L'istruzione WHERE si basa sul primo LEFT JOIN (pm) in modo che sappia che ho bisogno solo dei post in cui i metadati corrispondono.

Aggiungo anche un 'AND' per il tipo di post e per i post_status che non sono bozze. (quindi solo post pubblicati)

Infine aggiungo la clausola 'ordina per'.

Funziona velocemente e con gli indici integrati in Wordpress, quindi sembra efficiente.

Non so se qualcosa è meglio di così, ma se lo è, mi piacerebbe usarlo.

Spero che sia di aiuto.

Marcus


Grazie, questo post è molto utile. Ho creato una vista con tutti i meta campi di cui ho bisogno e ora è molto veloce e facile ottenere tutti i dati che desidero
Liko,

0

Ehi, per favore, prova questo, penso che funzioni bene.

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

    $query = new WP_Query( $args );

Qual è il motivo che hai usato meta_keye meta_query[]['key']pure?
Kaiser,

1
No, questo non funziona e riporta l'array di post senza meta associati ad essi.
YemSalat,

3
meta_keye / o meta_querynon modificare il tipo di risultati restituiti, solo la query stessa.
BODA82,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.