Poate wp_query să returneze meta datele postărilor într-o singură cerere?
Aș dori să creez o interogare wp_query care să returneze meta datele postărilor în interiorul array-ului posts
.
$args = array (
'post_type' => 'page',
'meta_key' => 'someMetaKeyName',
);
// Interogarea
$query = new WP_Query( $args );
Aceasta returnează ceva de genul:
După cum puteți vedea, postările nu au nicio meta dată, este posibil să includem meta datele în array-ul returnat de asemenea?
PS Nu doresc interogări wp_queries suplimentare din motive de performanță.

În mod implicit, WP_Query
returnează obiectele standard WP_Post
pentru postările interogate. Cred că, cu o rescriere inteligentă și utilizarea filtrelor furnizate în WP_Query
, poți adăuga obiecte la tabloul de obiecte WP_Post
returnat.
Va fi acest lucru performant? După părerea mea, va afecta performanța mai mult, deoarece va trebui să alături rezultate în interogarea ta, deoarece câmpurile personalizate nu sunt salvate în tabelul wp_posts
, ci în tabelul wp_postmeta
.
Preluarea metadatelor postărilor este foarte rapidă și nu necesită nicio instanță suplimentară a WP_Query
. Poți apela simplu câmpul personalizat cu get_post_meta()
. WordPress a fost foarte grijuliu când au fost introduse câmpurile personalizate. Au adăugat un cache pentru a le stoca, astfel încât indiferent dacă interoghezi 1 sau 100 de câmpuri personalizate, accesezi baza de date o singură dată, foarte rapid. Pentru un test complet și o explicație, vezi acest articol pe care l-am scris recent pe acest subiect.
În opinia mea, apelul suplimentar la baza de date și timpul efectiv petrecut merită și este mai rapid decât rescrierea WP_Query
într-un mod care să includă câmpurile personalizate în obiectul standard de post returnat de $posts
.

OK, mulțumesc, voi alege acest răspuns ca acceptat, dar să fiu sincer, este atât de obositor să apelezi get_post_meta()
pentru fiecare post în parte.. Aș prefera să existe o modalitate de a stoca date suplimentare fie direct în tabela wp_posts
, fie într-o tabelă asociată care nu este atât de complicată precum wp_postsmeta
.

Ei bine, să fiu sincer, indiferent dacă apelezi get_post_meta()
sau o folosești ca obiect post, va trebui să o apelezi pentru fiecare post. Este la fel cu funcțiile de tip template precum the_content()
, trebuie să le apelezi pentru fiecare post.

Asta înseamnă că dacă trebuie să afișezi 120 de postări, vei avea încă 120 de interogări suplimentare pe pagină?

Toate datele postării sunt salvate într-un cache, astfel încât nu veți avea interogări suplimentare când apelați meta postării

Am avut o problemă similară recent, aveam nevoie să obțin 7 câmpuri de metadate dintr-un tip de postare personalizat, dar și să obțin postarea bazată pe un câmp de metadate.
Așa că am creat următoarea declarație SQL, pe care o folosesc des. Sper să ajute pe cineva. Încerc să o explic cât mai bine posibil.
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 );
Mai întâi obțin funcțiile de bază de date WordPress cu global $wpdb. Apoi setez tipul de postare cu $pt. Pentru a obține postarea corectă care se potrivește cu o valoare specifică în post_meta, setez $mk (meta_key)
Apoi setez variabila $mv (meta_value) (în acest caz valoarea meta se potrivește cu un ID de postare)
$mk1-$mk7 sunt cheile meta pe care le doresc de la fiecare postare. (Le voi prelua valorile în declarația SELECT)
De asemenea, fac clauza 'order by' o variabilă, setând $ord
Declarația SELECT merge astfel: Selectez ID-ul postării și post_title din POST sau 'p.'
Apoi selectez toate metadatele de care am nevoie selectându-le cu pm1. -> pm.7 și preluând meta_value și redenumindu-le (AS) pentru a fi mai ușor de citit când preiau datele din obiectul meu.
Creez un LEFT JOIN pentru metadatele pe care trebuie să le potrivesc cu postarea. (pm)
Creez 7 LEFT JOIN-uri pentru fiecare dintre metadatele pe care trebuie să le obțin. (pm1-pm7)
Clauza WHERE se bazează pe primul LEFT JOIN (pm) astfel încât să știe că am nevoie doar de postările unde metadatele se potrivesc.
De asemenea, adaug o condiție 'AND' pentru tipul de postare și pentru post_status-urile care nu sunt draft. (deci doar postări publicate)
În final, adaug clauza 'order by'.
Această metodă funcționează rapid și folosind indexurile încorporate în WordPress, deci pare eficientă.
Nu știu dacă există ceva mai bun decât asta, dar dacă există, aș dori să-l folosesc.
Sper că vă ajută.
Marcus

Această întrebare are mai mult de 1 an, dar am aceeași problemă, iar aici este o funcție care va adăuga fiecare meta_value și meta_key la obiectul $wp_query,
în loc să interogăm fiecare post meta în bucla while, această funcție va face o singură interogare suplimentară exemplu:
"SELECT meta_key, meta_value, post_id FROM $wpdb->postmeta WHERE post_id IN (1,2,3,4,5...)"
unde (1,2,3,4,5...) sunt ID-urile posturilor curent interogate din $wp_query
if(!function_exists('add_query_meta')) {
function add_query_meta($wp_query = "") {
// Returnează dacă wp_query este gol sau dacă postmeta există deja
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;
}
}
Informația suplimentară "postmeta" va fi adăugată la fiecare $wp_query->posts[$i]
$wp_query->posts[0]->postmeta
Exemplu cu 'someMetaKeyName' nu uitați să adăugați
add_query_meta()
în fișierul functions.php al temei
$args = array (
'post_type' => 'page',
'meta_key' => 'someMetaKeyName',
);
// Interogarea
$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();
//Obține $someMetaKeyName în postul curent
foreach($wp_query->posts[$i]->postmeta as $k => $v) {
switch($v->meta_key) {
case('someMetaKeyName') : {
$someMetaKeyName = $v->meta_value;
break;
}
}
}
//Codul tău aici
//Exemplu
echo isset($someMetaKeyName) ? '<h3>'.$someMetaKeyName.'</h3>' : '';
$i++;
}
}

Am avut nevoie doar de o singură valoare suplimentară pentru post_meta (șablonul în cazul meu) și am reușit să obțin ceva similar cu ceea ce cauți folosind get_pages
cu un parametru meta_key
.
$args = [
'parent' => $post_id, // în exemplul meu, găsesc copiii unui anumit post
'meta_key' => '_wp_page_template', // caut șablonul folosit de post
];
$posts = get_pages($args);
Și aceasta returnează un array de obiecte post ca acesta
Array
(
[0] => WP_Post Object
(
[ID] => 22765
[post_author] => 173
[post_date] => 2022-03-14 21:11:18
...
[meta_key] => _wp_page_template
[meta_value] => template-module-content.php // <-- AICI E!
...
)
Și apoi poți accesa o valoare meta_value
astfel
echo $posts[0]->meta_value;
// returnează 'template-module-content.php' în cazul meu
Recunosc, acest lucru poate fi util doar într-un caz specific, dar era exact ceea ce aveam nevoie

Care este motivul pentru care ai folosit atât meta_key
cât și meta_query[]['key']
?

Nu, acest lucru nu funcționează și returnează matricea de postări fără meta asociate cu ele.
