Wp_query peut-il renvoyer des méta de messages en une seule demande?

22

Je voudrais créer un wp_query qui retournerait des méta de messages à l'intérieur du poststableau.

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

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

Cela renvoie quelque chose comme:

entrez la description de l'image ici

Comme vous pouvez le voir, 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.

YemSalat
la source
2
Le WP_Query standard ne renvoie pas de métadonnées de publications. Les seules options dont vous disposez sont les suivantes: 1) exécuter get_post_metasur des clés individuelles, 2) exécuter get_post_custompour obtenir tous les champs personnalisés d'un article en une seule fois, ou 3) créer votre propre requête à l'aide de la classe $ wpdb ( get_results()) pour créer votre propre objet de retour . (Documentation de la classe $ wpdb: codex.wordpress.org/Class_Reference/wpdb )
BODA82

Réponses:

20

Par défaut, WP_Queryretourne les WP_Postobjets standard pour les publications interrogées. Je crois qu'avec une réécriture intelligente et l'utilisation des filtres fournis, WP_Queryvous pouvez ajouter des objets au WP_Posttableau d'objets retournés .

Est-ce que ce sera performant? À mon avis, cela nuira davantage aux performances car vous devrez joindre les résultats dans votre requête car les champs personnalisés ne sont pas enregistrés dans le wp_poststableau, mais dans le wp_postmetatableau

La récupération de la méta-publication 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 réfléchi lorsque les champs personnalisés ont été introduits. Ils ont ajouté un cache pour les mettre en cache, donc que vous interrogiez 1 ou 100 champs personnalisés, vous frappez la base de données une fois, très rapidement. Pour un test complet et une explication, voir ce post que j'ai récemment fait sur ce sujet.

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

Pieter Goosen
la source
OK, merci, je vais choisir celui-ci comme accepté, mais pour être honnête, c'est tellement compliqué d'appeler get_post_meta()pour chaque message .. Je préférerais qu'il y ait un moyen de stocker des données supplémentaires soit directement dans le wp_poststableau, soit dans un table connexe qui n'est pas autant d'un mindf * ck que wp_postsmetac'est.
YemSalat
Eh bien, pour être honnête, que ce get_post_meta()soit en tant qu'objet de publication, vous devrez l'appeler sur chaque publication. C'est la même chose avec des balises de modèle comme the_content(), vous devez l'appeler sur chaque publication.
Pieter Goosen
2
Cela signifie que si vous devez afficher 120 messages, vous aurez 120 requêtes supplémentaires dans votre page?
chifliiiii
Toutes les données postérieures sont enregistrées dans un cache, vous n'aurez donc pas de requêtes supplémentaires lors de la cal; ling post meta
Pieter Goosen
Tu as raison. Je faisais référence à post_thumbnails mais j'ai récemment trouvé update_post_thumbnail_cache ($ the_query). Merci quand même pour la clarification
chifliiiii
4

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

au lieu d'interroger chaque méta post dans la boucle while, cette fonction fera un exemple de requête supplémentaire:

"SELECT meta_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 les ID de publication recherchés 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++;
    }
}
Jonny
la source
J'adore cette solution.
Armstrongest
3

J'ai eu un problème similaire récemment, j'avais besoin d'obtenir 7 morceaux de métadonnées à partir d'un type de message personnalisé, mais j'avais également besoin d'obtenir le message en fonction d'un morceau de métadonnées.

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

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

Ensuite, j'ai défini la var $ mv (meta_value). (dans ce cas, la méta-valeur correspond à un postid)

$ mk1- $ mk7 sont les meta_keys que je veux de chaque article. (Je vais saisir les valeurs dans l'instruction select)

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

L'instruction select se présente comme suit: je sélectionne l'ID du post et le post_title dans le POST ou 'p.'

Ensuite, je sélectionne toutes les métadonnées dont j'ai besoin en les sélectionnant avec pm1. -> pm.7 et en saisissant la méta_valeur et en les renommant (AS) afin qu'elle soit plus lisible lors de la récupération des données de mon objet.

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

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

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

J'ajoute également un «ET» pour le type de message et pour les post_status qui ne sont pas des brouillons. (donc seuls les articles publiés)

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

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

Je ne sais pas si quelque chose est meilleur que ça, mais si c'est le cas, j'adorerais l'utiliser.

J'espère que cela t'aides.

Marcus

Marcus
la source
Merci, ce message est très utile. J'ai créé une vue avec tous les champs méta dont j'ai besoin et il est maintenant très rapide et facile d'obtenir toutes les données que je veux
Liko
0

Hé, essayez celui-ci, je pense que ça marche bien.

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

    $query = new WP_Query( $args );
Amit Mishra
la source
Quelle est la raison pour laquelle vous avez utilisé meta_keyet meta_query[]['key']aussi bien?
kaiser
1
Non, cela ne fonctionne pas et ramène le tableau des messages sans méta associé.
YemSalat
3
meta_keyet / ou meta_queryne modifiez pas le type de résultats retournés, uniquement la requête elle-même.
BODA82