Чи може wp_query повертати мета-повідомлення в одному запиті?


22

Я хотів би створити wp_query, який би повертав мета повідомлення у postsмасиві.

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

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

Це повертає щось на кшталт:

введіть тут опис зображення

Як ви бачите, у публікаціях немає жодних метаданих, чи можливо включити метадані і у повернутий масив?

PS Я не хочу додаткових wp_queries з міркувань продуктивності.


2
Стандартний WP_Query не повертає метадані публікацій. Єдині варіанти: 1) запустити get_post_metaокремі клавіші; 2) запустити, get_post_customщоб отримати всі користувацькі поля за один кадр, або 3) створити власний запит, використовуючи клас $ wpdb ( get_results()) для створення власного об'єкта повернення . (Документація по класу $ wpdb: codex.wordpress.org/Class_Reference/wpdb )
BODA82

Відповіді:


20

За замовчуванням WP_Queryповертає стандартні WP_Postоб'єкти для запитів, що запитуються. Я вважаю, що за допомогою розумного перезапису та використання наведених у WP_Queryвас фільтрів ви можете додавати об'єкти до WP_Postмасиву, що повертається .

Це буде виконавцем? На мою думку, це більше зашкодить продуктивності, оскільки вам потрібно буде приєднати результати до свого запиту, оскільки спеціальні поля зберігаються не в wp_postsтаблиці, а в wp_postmetaтаблиці

Отримання мета мета дуже швидко, і для цього не потрібні додаткові екземпляри WP_Query. Ви можете просто зателефонувати за допомогою спеціального поля за допомогою get_post_meta(). WordPress був дуже продуманим, коли було запроваджено спеціальні поля. Вони додали кеш, щоб кешувати їх, так що якщо ви запитуєте 1 або 100 користувацьких полів, ви одноразово потрапляєте в базу даних, надзвичайно швидко. Повний тест та пояснення дивіться у цій публікації, яку я нещодавно робив з цього приводу.

На мою думку, додатковий виклик бази даних та фактично витрачений час вартий цього і швидше, ніж переписування WP_Queryтаким чином, щоб включити користувацькі поля в стандартний об'єкт поштового зв’язку, повернутий$posts


Добре, спасибі, я підберу цей як прийнятий, але якщо чесно, його так багато клопотів, що вимагають get_post_meta()кожного повідомлення. Я вважаю за краще існувати спосіб зберігати додаткові дані безпосередньо в wp_postsтаблиці, або в пов'язана таблиця, яка не стільки mindf * ck, скільки wp_postsmetaє.
YemSalat

Ну, якщо чесно, незалежно get_post_meta()від того, дзвоніть чи це як об’єкт поштового зв’язку, вам потрібно буде дзвонити на кожну посаду. Це те саме з тегами шаблонів, як the_content(), ви повинні називати його на кожній публікації.
Пітер Гусен

2
Це означає, що якщо вам доведеться показати 120 публікацій, у вас з’являться додаткові 120 запитів на вашій сторінці?
chifliiiii

Усі дані будуть збережені в кеші, тому у вас не буде зайвих запитів під час виклику; ling post meta
Pieter Goosen

Ти правий. Я мав на увазі post_thumbnails, але нещодавно знайшов update_post_thumbnail_cache ($ the_query). Все одно дякую за роз’яснення
chifliiiii

4

Це питання більше 1 року, але у мене той самий проблем, і ось функція, яка додасть кожен meta_value та meta_key до $ wp_query об'єкта,

замість запиту кожного мета-повідомлення в циклі while, ця функція зробить один додатковий приклад запиту:

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

де (1,2,3,4,5 ...) поточно запитуються ідентифікатори публікації з $ 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;
  }
}

Додатковий "постмета" буде записаний у кожну публікацію $ wp_query-> [$ i]

$wp_query->posts[0]->postmeta

Приклад із "someMetaKeyName" не забудьте поставити

add_query_meta() до вашої теми 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++;
    }
}

Я люблю це рішення.
Армстронгест

3

У мене була подібна проблема нещодавно, мені потрібно було отримати 7 фрагментів метаданих від користувальницького типу публікації, але також потрібно було отримати публікацію на основі фрагмента метаданих.

Тому я створив наступний оператор SQL, використовую його часто. Сподіваємось, це допоможе комусь іншому. Я спробую пояснити це якнайкраще.

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

Спочатку я отримую функції бази даних wordpress із глобальним $ wpdb. Потім я встановив посттип $ pt. Щоб отримати правильну публікацію, яка відповідає конкретному значенню в post_meta, я встановив $ mk (meta_key)

Тоді я встановлюю var $ mv (meta_value) var. (у цьому випадку мета-значення відповідає postid)

$ mk1- $ mk7 - це мета-ключі, які я хочу від кожної публікації. (Я захоплюю значення у операторі select)

Я також роблю вар. "Порядок", встановивши $ ord

Оператор select виглядає наступним чином: я вибираю ідентифікатор публікації та post_title з POST або «p».

Потім я вибираю всі метадані, потрібні для їх вибору, з pm1. -> pm.7 і захоплення мета_значення та перейменування їх (AS), щоб воно було більш читабельним при отриманні даних з мого об’єкта.

Я створюю СПІЛЬНИЙ ПРИЄДНАЙТЕ для метаданих, які мені потрібні, щоб відповідати публікації. (вечора)

Я створюю 7 лівих з'єднань для кожної з метаданих, які мені потрібно отримати. (pm1-pm7)

Заява WHERE заснована на першому лівому приєднанні (pm), щоб він знав, що мені потрібні лише пости, де метадані відповідають.

Я також додаю "І" для типу публікації та для post_statuses, які не є чернетками. (так тільки опубліковані повідомлення)

Нарешті я додаю пункт "порядок за".

Це працює швидко та із вбудованими індексами в Wordpress, тому здається ефективним.

Не знаю, чи щось краще, ніж це, але якщо воно є, я б хотів це використати.

Сподіваюсь, це допомагає.

Маркус


Дякую, ця публікація дуже корисна. Я створив перегляд усіх потрібних мені мета-полів, і зараз дуже швидко та легко отримати будь-які потрібні мені дані
Liko

0

Гей, будь ласка, спробуйте цей, я думаю, це працює добре.

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

    $query = new WP_Query( $args );

У чому причина, яку ви використовували meta_keyі meta_query[]['key']так само?
кайзер

1
Ні, це не працює і повертає масив публікацій без мета, пов’язаних з ними.
YemSalat

3
meta_keyта / або meta_queryне змінюють тип результатів, що повертаються, лише сам запит.
BODA82
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.