Может ли wp_query возвращать мета-сообщения в одном запросе?

22

Я хотел бы создать wp_query, который возвращал бы мета сообщений внутри postsмассива.

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

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

Это возвращает что-то вроде:

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

Как вы можете видеть, посты не имеют метаданных, возможно ли включить метаданные в возвращаемый массив?

PS Я не хочу дополнительные wp_queries по соображениям производительности.

YemSalat
источник
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таким образом, чтобы включить настраиваемые поля в стандартный объект post, возвращаемый$posts

Питер Гусен
источник
Хорошо, спасибо, я выберу это как принятое, но, честно говоря, это просто так много хлопот get_post_meta()для каждого поста ... Я бы предпочел, чтобы был способ сохранить дополнительные данные либо непосредственно в wp_postsтаблице, либо в связанная таблица, которая не так уж и важна, как wp_postsmetaесть.
YemSalat
Ну, если честно, звоните ли вы get_post_meta()или это как объект сообщения, вам нужно будет вызывать его в каждом сообщении. То же самое относится и к шаблонным тегам, например the_content(), вы должны вызывать это в каждом сообщении.
Питер Гусен
2
Это означает, что если вам нужно показать 120 сообщений, у вас будет 120 дополнительных запросов на вашей странице?
Чифлииий
Все постданные сохраняются в кеше, поэтому у вас не будет лишних запросов при вызове мета-поста
Pieter Goosen
Вы правы. Я имел в виду post_thumbnails, но недавно обнаружил update_post_thumbnail_cache ($ the_query). В любом случае спасибо за разъяснение
chifliiiii
4

Этому вопросу более 1 года, но у меня тот же пробломлем, и вот функция, которая будет добавлять каждое meta_value и meta_key к объекту $ wp_query,

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

«ВЫБЕРИТЕ meta_key, meta_value, post_id FROM $ wpdb-> postmeta ГДЕ 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;
  }
}

Дополнительная запись "postmeta" будет записана в каждый $ wp_query-> posts [$ 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++;
    }
}
Jonny
источник
Я люблю это решение.
Армстронг
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. Затем я установил posttype с помощью $ pt. Чтобы получить правильный пост, который соответствует определенному значению в post_meta, я установил $ mk (meta_key)

Затем я установил переменную $ mv (meta_value). (в этом случае мета-значение соответствует postid)

$ mk1- $ mk7 - мета-ключи, которые я хочу от каждого поста. (Я возьму значения в операторе выбора)

Я также делаю 'order by' var, устанавливая $ ord

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

Затем я выбираю все нужные мне метаданные с помощью pm1. -> pm.7 и захват meta_value и переименование их (AS), чтобы он был более читабельным при извлечении данных из моего объекта.

Я создаю LEFT JOIN для метаданных, которые мне нужно сопоставить с постом. (вечера)

Я создаю 7 левых соединений для каждой метаданной, которую мне нужно получить. (PM1-PM7)

Оператор WHERE основан на первом LEFT JOIN (pm), поэтому он будет знать, что мне нужны только сообщения, для которых совпадают метаданные.

Я также добавляю «И» для типа записи и для post_statuses, которые не являются черновиками. (так только опубликованные посты)

Наконец, я добавляю предложение 'order by'.

Это работает быстро и со встроенными индексами в 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