wp_query peut-il retourner des méta en une seule requête?

17

Je voudrais créer une requête wp_query qui renverrait les posts méta à l'intérieur du tableau posts .

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

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

Ceci retourne quelque chose comme:

Comme vous pouvez le constater, les publications ne contiennent aucune métadonnée, est-il possible d'inclure également les métadonnées dans le tableau renvoyé?

PS: je ne veux pas de wp_queries supplémentaires pour des raisons de performances.

    
posée YemSalat 12.12.2014 - 04:09

4 réponses

17

Par défaut, WP_Query renvoie la norme WP_Post des objets pour les publications interrogées. Je crois qu'avec une réécriture astucieuse et l'utilisation des filtres donnés dans WP_Query , vous pouvez ajouter des objets au tableau WP_Post d'objets renvoyé.

Sera-ce performant. À mon avis, les performances seront d'autant plus affectées que vous devrez joindre des résultats, car les champs personnalisés ne sont pas enregistrés dans la table wp_posts , mais dans la table wp_postmeta

La récupération de post meta est très rapide et ne nécessite aucune instance supplémentaire de WP_Query . Vous pouvez simplement appeler le champ personnalisé avec get_post_meta() . Wordpress a beaucoup réfléchi lorsque les champs personnalisés ont été introduits. Ils ont ajouté un cache pour les mettre en cache. Ainsi, que vous interrogiez 1 ou 100 champs personnalisés, vous frappez la base de données une fois, ultra-rapide. Pour un test complet et des explications, voir ce message que j'ai récemment rédigé à ce sujet

.

À mon avis, l'appel supplémentaire à la base de données et le temps passé en valent la peine et sont plus rapides que la réécriture de WP_Query de manière à inclure des champs personnalisés dans l'objet de publication standard renvoyé par $posts

    
réponse donnée Pieter Goosen 12.12.2014 - 05:37
4

J'ai eu un problème similaire récemment, je devais obtenir 7 métadonnées à partir d'un type de publication personnalisé, mais j'avais également besoin que la publication soit basée sur une métadonnée.

J'ai donc créé l'instruction SQL suivante, je l'utilise souvent. J'espère que cela aidera quelqu'un d'autre. Je vais essayer de l'expliquer du mieux que je peux.

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

Tout d’abord, j’obtiens les fonctions de base de données wordpress avec le global $ wpdb. Ensuite, je configure le type de message avec $ pt. Pour obtenir le post correct qui correspond à une valeur spécifique dans post_meta, j'ai défini le paramètre $ mk (meta_key)

Ensuite, je définis la variable $ mv (meta_value). (dans ce cas, la méta valeur correspond à un postid)

$ mk1- $ mk7 sont les méta_keys que je veux dans chaque message. (Je vais prendre les valeurs dans l'instruction select)

Je fais aussi le 'commande par' une var, en mettant $ ord

L'instruction select est la suivante: Je sélectionne le post ID et le post_title dans le POST ou 'p.'

Ensuite, je sélectionne toutes les métadonnées dont j'ai besoin avec pm1. - > pm.7 et en récupérant la meta_value et en les renommant (AS) afin de les rendre plus lisibles lors de la récupération des données de mon objet.

Je crée un JOINDRE GAUCHE pour les métadonnées que je dois faire correspondre à la publication. (pm)

Je crée 7 jointures restantes pour chacune des métadonnées que je dois récupérer. (pm1-pm7)

L'instruction WHERE est basée sur le premier LEFT JOIN (pm) afin qu'il sache que je n'ai besoin que des publications où les métadonnées correspondent.

J'ajoute également un "AND" pour le type de publication et pour les statuts de post qui ne sont pas des brouillons. (donc uniquement les posts publiés)

Enfin, j'ajoute la clause 'order by'.

Cela fonctionne rapidement et avec les index intégrés dans Wordpress, cela semble donc efficace.

Je ne sais pas si quelque chose est mieux que cela, mais si c'est le cas, j'aimerais bien l'utiliser.

J'espère que cela aide.

Marcus

    
réponse donnée Marcus 14.02.2017 - 02:21
3

Cette question a plus d'un an, mais j'ai le même problème, et voici une fonction qui ajoutera chaque méta_valeur et chaque méta_key à l'objet $ wp_query,

au lieu d’interroger chaque méta de post en boucle while, cette fonction effectuera une interrogation supplémentaire exemple:

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

où (1,2,3,4,5 ...) est actuellement demandé les identifiants de post 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;
  }
}

Un "postmeta" supplémentaire sera écrit dans chaque $ wp_query- > posts [$ i]

$wp_query->posts[0]->postmeta

Exemple avec 'someMetaKeyName', n'oubliez pas de mettre

add_query_meta() à votre thème 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++;
    }
}
    
réponse donnée Jonny 05.05.2016 - 15:10
0

Hé, s'il te plaît, essaie celui-là, je pense que ça marche très bien.

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

    $query = new WP_Query( $args );
    
réponse donnée Amit Mishra 12.12.2014 - 04:44

Lire d'autres questions sur les étiquettes