web-dev-qa-db-fra.com

Wp_query peut-il afficher des méta en une seule requête?

Je voudrais créer un wp_query qui renverrait des méta de poteaux à l'intérieur du tableau posts.

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

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

Cela retourne quelque chose comme:

enter image description here

Comme vous pouvez le constater, les publications n’ont pas de métadonnées, 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.

20
YemSalat

Par défaut, WP_Query renvoie les objets standard WP_Post pour les articles interrogés. 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 d'objets WP_Post renvoyés.

Sera-ce performant? À mon avis, les performances vont en souffrir davantage, car vous devrez joindre les résultats de votre requête, car les champs personnalisés ne sont pas enregistrés dans la table wp_posts, mais dans la table wp_postmeta.

Récupérer 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 était très attentionné 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 une explication, voir cet article je l’ai fait récemment sur ce sujet.

À mon avis, l'appel supplémentaire à la base de données et le temps réellement 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

20
Pieter Goosen

J'ai eu un problème similaire récemment, je devais obtenir 7 métadonnées à partir d'un type de publication personnalisé, mais je devais aussi obtenir la publication 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 );

Je reçois d’abord les fonctions de base de données wordpress avec $ wpdb global. Ensuite, je règle le type de message avec $ pt. Pour obtenir le post correct qui correspond à une valeur spécifique dans post_meta, je règle le $ mk (meta_key)

Ensuite, je mets 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 post. (Je vais prendre les valeurs dans l'instruction select)

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

L'instruction select va comme suit: Je sélectionne l'ID de l'article et le titre de l'article 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 l'extraction des données de mon objet.

Je crée un JOINT GAUCHE pour les métadonnées dont j'ai besoin pour correspondre à la publication. (pm)

Je crée 7 jointures à gauche 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 sur lesquelles les métadonnées correspondent.

J'ajoute aussi un 'AND' pour le type d'article et pour les post_statuses qui ne sont pas des brouillons. (donc seulement 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 t'aides.

Marcus

4
Marcus

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

au lieu d’interroger chaque boucle meta de publication en boucle while, cette fonction fera un exemple de requête supplémentaire:

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

où (1,2,3,4,5 ...) est actuellement interrogé par 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++;
    }
}
3
Jonny

Hey S'il vous plaît essayez celui-ci, je pense que cela fonctionne bien.

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

    $query = new WP_Query( $args );
0
Amit Mishra