Ich möchte eine wp_query erstellen, die Posts-Meta innerhalb des Arrays posts
zurückgibt.
$args = array (
'post_type' => 'page',
'meta_key' => 'someMetaKeyName',
);
// The Query
$query = new WP_Query( $args );
Das ergibt so etwas wie:
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.
Standardmäßig gibt WP_Query
die Standardobjekte WP_Post
für die abgefragten Posts zurück. Ich glaube, mit einigen cleveren Änderungen und der Verwendung der in WP_Query
angegebenen Filter können Sie dem zurückgegebenen WP_Post
objects-Array 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 Tabelle wp_posts
, sondern in der Tabelle wp_postmeta
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 get_post_meta()
aufrufen. 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. Für einen vollständigen Test und eine Erklärung siehe diesen Beitrag den ich kürzlich zu diesem Thema gemacht habe.
Meiner Meinung nach lohnt sich der zusätzliche Datenbankaufruf und die tatsächlich aufgewendete Zeit und sind schneller als das Umschreiben von WP_Query
, sodass benutzerdefinierte Felder in das von $posts
zurückgegebene Standardpostobjekt einbezogen werden.
Vor kurzem hatte ich ein ähnliches Problem. Ich musste 7 Metadaten eines benutzerdefinierten Beitragstyps abrufen, aber ich musste den Beitrag auch auf der Grundlage von Metadaten abrufen.
Deshalb 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 die 'order by' ein var, indem ich $ ord setze
Die select-Anweisung lautet wie folgt: Ich wähle die Beitrags-ID und den Beitragstitel 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 Joins 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
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++;
}
}
Hey, bitte versuchen Sie es mit diesem, 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 );