Kann wp_query Beiträge in einer einzelnen Anfrage als Meta zurückgeben?

22

Ich möchte eine wp_query erstellen, die Posts-Meta innerhalb des postsArrays zurückgibt .

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

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

Das ergibt so etwas wie:

Bildbeschreibung hier eingeben

Wie Sie sehen, haben die Posts keine Metadaten. Ist es möglich, die Metadaten auch in das zurückgegebene Array aufzunehmen?

PS Ich möchte aus Performancegründen keine zusätzlichen wp_queries.

YemSalat
quelle
2
Die Standard-WP_Query gibt keine Metadaten für Posts zurück. Die einzigen Optionen, die Sie haben, sind: 1) Ausführen get_post_metamit einzelnen Schlüsseln, 2) Ausführen get_post_custom, um alle benutzerdefinierten Felder eines Posts auf einmal abzurufen, oder 3) Erstellen einer eigenen Abfrage mit der Klasse $ wpdb ( get_results()), um Ihr eigenes Rückgabeobjekt zu erstellen . ($ wpdb class documentation: codex.wordpress.org/Class_Reference/wpdb )
BODA82

Antworten:

20

Standardmäßig werden WP_Querydie Standardobjekte WP_Postfür die abgefragten Posts zurückgegeben. Ich glaube, mit einigem geschickten Umschreiben und der Verwendung der Filter in WP_Querykönnen Sie dem WP_PostArray der zurückgegebenen Objekte Objekte hinzufügen .

Wird das performant sein? Meiner Meinung nach beeinträchtigt dies die Leistung, da Sie die Ergebnisse in Ihrer Abfrage zusammenführen müssen, da benutzerdefinierte Felder nicht in der wp_postsTabelle, sondern in der wp_postmetaTabelle gespeichert werden

Das Abrufen von Post-Meta ist sehr schnell und erfordert keine zusätzliche Instanz von WP_Query. Sie können das benutzerdefinierte Feld einfach mit aufrufen get_post_meta(). WordPress war sehr nachdenklich, als die benutzerdefinierten Felder eingeführt wurden. Sie haben einen Cache hinzugefügt, um sie zwischenzuspeichern. Unabhängig davon, ob Sie 1 oder 100 benutzerdefinierte Felder abfragen, treffen Sie die Datenbank einmal, superschnell. Einen vollständigen Test und eine Erklärung finden Sie in diesem Beitrag, den ich kürzlich zu diesem Thema verfasst habe.

Meiner Meinung nach lohnt sich der zusätzliche Datenbankaufruf und die tatsächlich aufgewendete Zeit und sind schneller als das Umschreiben WP_Query, um benutzerdefinierte Felder in das von zurückgegebene Standard-Post-Objekt aufzunehmen$posts

Pieter Goosen
quelle
OK, danke, werde ich diese wählen als angenommen, aber ehrlich sein gerade so viel Aufwand Aufruf zu sein get_post_meta()für jeden einzelnen Post .. Ich würde eher war es eine Möglichkeit , zusätzliche Daten zu speichern , entweder direkt in der wp_postsTabelle oder in ein verwandte Tabelle, die nicht so ein Geist ist, wie es wp_postsmetaist.
YemSalat
Um ehrlich zu sein get_post_meta(), müssen Sie es bei jedem Post aufrufen, egal ob es sich um einen Call handelt oder um ein Post-Objekt. Das gleiche gilt für Template-Tags the_content(), die Sie bei jedem Beitrag aufrufen müssen.
Pieter Goosen
2
Das heißt, wenn Sie 120 Posts anzeigen müssen, haben Sie zusätzliche 120 Abfragen auf Ihrer Seite?
Chifliiiii
Alle Postdaten werden in einem Cache gespeichert, so dass Sie keine zusätzlichen Fragen haben, wenn Sie das Post-Meta aufrufen
Pieter Goosen
Du hast recht. Ich bezog mich auf post_thumbnails, fand aber kürzlich update_post_thumbnail_cache ($ the_query).
Trotzdem vielen
4

Diese Frage ist mehr als 1 Jahr alt, aber ich habe das gleiche Problem, und hier ist eine Funktion, die jeden meta_value und meta_key zum $ wp_query-Objekt hinzufügt.

Anstatt jede Post-Meta-In-While-Schleife abzufragen, führt diese Funktion ein zusätzliches Abfragebeispiel aus:

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

Dabei ist (1,2,3,4,5 ...) die aktuelle Post-ID von $ 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;
  }
}

Zusätzliche "Postmeta" werden in jeden $ wp_query-> Post geschrieben [$ i]

$wp_query->posts[0]->postmeta

Beispiel mit 'someMetaKeyName' vergessen Sie nicht zu setzen

add_query_meta() zu deinem Theme 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
quelle
Ich liebe diese Lösung.
Armstrongest
3

Vor kurzem hatte ich ein ähnliches Problem. Ich musste 7 Metadaten eines benutzerdefinierten Beitragstyps abrufen, aber ich musste auch den Beitrag auf der Grundlage von Metadaten abrufen.

Daher habe ich die folgende SQL-Anweisung erstellt, die ich häufig verwende. Hoffentlich hilft es jemand anderem. Ich werde versuchen, es so gut wie möglich zu erklären.

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

Zuerst bekomme ich die WordPress-Datenbankfunktionen mit globalem $ wpdb. Dann setze ich den Posttyp mit $ pt. Um den korrekten Beitrag zu erhalten, der einem bestimmten Wert in post_meta entspricht, setze ich $ mk (meta_key)

Dann setze ich die Variable $ mv (meta_value). (In diesem Fall stimmt der Meta-Wert mit einer Post-ID überein.)

$ mk1- $ mk7 sind die Metaschlüssel, die ich von jedem Beitrag haben möchte. (Ich werde die Werte in der Select-Anweisung greifen)

Ich mache auch das 'order by' ein var, indem ich $ ord setze

Die select-Anweisung lautet wie folgt: Ich wähle die Post-ID und den post_title aus dem POST oder 'p.'

Dann wähle ich alle Metadaten aus, die ich mit pm1 auswählen muss. -> pm.7 und nimm den meta_value und benenne ihn um (AS), damit er besser lesbar ist, wenn du die Daten von meinem Objekt abrufst.

Ich erstelle einen LEFT JOIN für die Metadaten, die ich für den Beitrag benötige. (pm)

Ich erstelle 7 linke Verknüpfungen für jede der Metadaten, die ich abrufen muss. (pm1-pm7)

Die WHERE-Anweisung basiert auf dem ersten LEFT JOIN (pm), sodass ich nur die Posts benötige, bei denen die Metadaten übereinstimmen.

Ich füge auch ein "UND" für den Beitragstyp und für die post_statuses hinzu, die keine Entwürfe sind. (also nur veröffentlichte Beiträge)

Schließlich füge ich die 'order by'-Klausel hinzu.

Dies funktioniert schnell und mit den in Wordpress integrierten Indizes. Es scheint also effizient zu sein.

Ich weiß nicht, ob etwas besser ist als dieses, aber wenn ja, würde ich es gerne verwenden.

Hoffe das hilft.

Marcus

Marcus
quelle
Danke, dieser Beitrag ist sehr hilfreich. Ich habe eine Ansicht mit allen Metafeldern erstellt, die ich benötige, und jetzt ist es sehr schnell und einfach, alle gewünschten Daten
abzurufen
0

Hey, bitte versuchen Sie es hier, ich denke, es funktioniert gut.

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

    $query = new WP_Query( $args );
Amit Mishra
quelle
Was ist der Grund, warum du das benutzt hast meta_keyund meta_query[]['key']auch?
Kaiser
1
Nein, dies funktioniert nicht und bringt das Array der Posts ohne zugeordnetes Meta zurück.
YemSalat
3
meta_keyund / oder meta_queryändern Sie nicht die Art der zurückgegebenen Ergebnisse, sondern nur die Abfrage selbst.
BODA82