Czy wp_query może zwrócić posty meta w jednym żądaniu?

22

Chciałbym utworzyć wp_query, które zwracałyby meta postów wewnątrz poststablicy.

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

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

Zwraca coś takiego:

wprowadź opis zdjęcia tutaj

Jak widać posty nie zawierają żadnych metadanych, czy można również uwzględnić metadane w zwróconej tablicy?

PS Nie chcę dodatkowych wp_queries ze względu na wydajność.

YemSalat
źródło
2
Standardowa WP_Query nie zwraca metadanych dotyczących postów. Jedyne opcje, jakie masz: 1) uruchomić get_post_metana poszczególnych kluczach, 2) uruchomić, get_post_customaby uzyskać wszystkie posty niestandardowe pola w jednym ujęciu, lub 3) utworzyć własne zapytanie za pomocą klasy $ wpdb ( get_results()), aby zbudować własny obiekt zwrotny . (Dokumentacja klasy $ wpdb: codex.wordpress.org/Class_Reference/wpdb )
BODA82

Odpowiedzi:

20

Domyślnie WP_Queryzwraca standardowe WP_Postobiekty dla odpytywanych postów. Wierzę, że dzięki sprytnemu przepisaniu i zastosowaniu podanych filtrów WP_Querymożesz dodawać obiekty do WP_Posttablicy zwróconych obiektów.

Czy to będzie skuteczne? Moim zdaniem bardziej pogorszy to wydajność, ponieważ będziesz musiał dołączyć wyniki w zapytaniu, ponieważ pola niestandardowe nie są zapisywane w wp_poststabeli, ale w wp_postmetatabeli

Pobieranie post meta jest bardzo szybkie i nie wymaga żadnego dodatkowego wystąpienia WP_Query. Możesz po prostu wywołać niestandardowe pole za pomocą get_post_meta(). WordPress był bardzo przemyślany, gdy wprowadzono niestandardowe pola. Dodali pamięć podręczną, aby je buforować, więc bez względu na to, czy pytasz o 1 czy 100 pól niestandardowych, trafiasz do bazy danych raz, superszybko. Aby uzyskać pełny test i wyjaśnienie, zobacz ten post , który ostatnio napisałem na ten temat.

Moim zdaniem dodatkowe wywołanie bazy danych i faktyczny czas są tego warte i szybsze niż przepisywanie WP_Queryw taki sposób, aby uwzględnić niestandardowe pola w standardowym obiekcie postu zwróconym przez$posts

Pieter Goosen
źródło
OK, dziękuję, wybiorę ten jako zaakceptowany, ale szczerze mówiąc, tyle kłopotów wymaga get_post_meta()każdego postu. Wolę istnieć sposób na przechowywanie dodatkowych danych albo bezpośrednio w wp_poststabeli, albo w pokrewna tabela, która nie jest aż tak bardzo mindf * ck jak wp_postsmetajest.
YemSalat,
Cóż, szczerze mówiąc, niezależnie od tego, czy dzwonisz, get_post_meta()czy jako post, będziesz musiał wywoływać go w każdym poście. To samo dotyczy tagów szablonów, takich jak the_content(), musisz wywoływać go w każdym poście.
Pieter Goosen,
2
Oznacza to, że jeśli musisz pokazać 120 postów, będziesz mieć dodatkowe 120 zapytań na swojej stronie?
chifliiiii
Wszystkie dane są zapisywane w pamięci podręcznej, więc nie będziesz mieć dodatkowych zapytań podczas cal; ling post meta
Pieter Goosen
Masz rację. Miałem na myśli post_thumbnails, ale ostatnio znalazłem update_post_thumbnail_cache ($ the_query). W każdym razie dziękuję za wyjaśnienie
chifliiiii
4

To pytanie ma ponad rok, ale mam ten sam problem, a oto funkcja, która doda każdą wartość meta_key i meta_key do obiektu $ wp_query,

zamiast zapytania do każdej meta post w pętli while ta funkcja wykona jeden dodatkowy przykład zapytania:

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

gdzie (1,2,3,4,5 ...) jest obecnie pytany o identyfikatory postów z $ 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;
  }
}

Dodatkowa „postmeta” zostanie zapisana do każdego $ wp_query-> postów [$ i]

$wp_query->posts[0]->postmeta

Przykład z „someMetaKeyName” nie zapomnij umieścić

add_query_meta() do motywu funkin.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
źródło
Uwielbiam to rozwiązanie.
Armstrongest
3

Miałem ostatnio podobny problem, musiałem uzyskać 7 elementów metadanych z niestandardowego typu posta, ale potrzebowałem też posta opartego na metadanych.

Utworzyłem więc następującą instrukcję SQL, używam jej często. Mam nadzieję, że pomoże to komuś innemu. Spróbuję to wyjaśnić najlepiej, jak potrafię.

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

Najpierw dostaję funkcje bazy danych wordpress z globalnym $ wpdb. Następnie ustawiam typ postu za pomocą $ pt. Aby uzyskać poprawny post, który pasuje do określonej wartości w post_meta, ustawiłem $ mk (meta_key)

Następnie ustawiam zmienną $ mv (meta_value). (w tym przypadku wartość meta odpowiada postidowi)

$ mk1- $ mk7 to meta_keys, które chcę od każdego postu. (Wezmę wartości w instrukcji select)

Wykonuję również „sortuj według” var, ustawiając $ ord

Instrukcja select wygląda następująco: wybieram identyfikator posta i post_title z POST lub „p”.

Następnie wybieram wszystkie metadane, których potrzebuję, wybierając je za pomocą pm1. -> pm.7 i pobieranie meta_value i zmiana ich nazwy (AS), aby było bardziej czytelne podczas pobierania danych z mojego obiektu.

Tworzę LEFT JOIN dla metadanych, które muszę dopasować do posta. (po południu)

Tworzę 7 lewych złączeń dla każdego z metadanych, które muszę pobrać. (pm1-pm7)

Instrukcja WHERE oparta jest na pierwszym LEWYM DOŁĄCZU (pm), aby wiedzieć, że potrzebuję tylko wpisów, w których pasują metadane.

Dodam również „AND” dla typu posta i dla post_statuses, które nie są wersjami roboczymi. (więc tylko opublikowane posty)

Na koniec dodaję klauzulę „sortuj według”.

Działa to szybko i dzięki wbudowanym indeksom w Wordpress, więc wydaje się wydajne.

Nie wiem, czy coś jest lepsze od tego, ale jeśli tak, chciałbym tego użyć.

Mam nadzieję że to pomoże.

Marcus

Marcus
źródło
Dzięki, ten post jest bardzo pomocny. Stworzyłem widok ze wszystkimi potrzebnymi meta polami, a teraz jest bardzo szybki i łatwy do uzyskania dowolnych danych
Liko
0

Hej, spróbuj tego, myślę, że działa dobrze.

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

    $query = new WP_Query( $args );
Amit Mishra
źródło
Co jest powodem, że stosowane meta_keyi meta_query[]['key']jak dobrze?
kaiser,
1
Nie, to nie działa i przywraca tablicę postów bez powiązanych z nimi meta.
YemSalat,
3
meta_keyi / lub meta_querynie modyfikuj typu zwracanych wyników, tylko samo zapytanie.
BODA82,