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,2014年

Answers:


20

默认情况下,WP_Query返回WP_Post要查询的帖子的标准对象。我相信通过巧妙地重写和使用给定的过滤器,WP_Query可以将对象添加到返回的WP_Post对象数组中。

这会表现吗?我认为,这将进一步降低性能,因为您需要在查询中加入结果,因为自定义字段未保存在wp_posts表中,而是在wp_postmeta表中

检索post meta确实非常快,并且不需要任何额外的实例WP_Query。您只需使用即可调用自定义字段get_post_meta()。引入自定义字段时,WordPress非常周到。他们添加了一个缓存来缓存它们,因此无论您要查询1个还是100个自定义字段,您都可以超快地访问数据库一次。有关完整的测试和解释,请参阅我最近在该主题上发表的这篇文章

在我看来,额外的数据库调用和实际花费的时间是值得的,并且比WP_Query以将自定义字段包括在由以下方法返回的标准post对象中的方式进行重写要快$posts


好的,谢谢,我会选择这个作为一个公认的,但说实话它只是这么多的麻烦,呼吁get_post_meta()为每一个职位..我宁愿有要么直接在存储附加数据的方式wp_posts表,或在相关表,并不是那么容易wp_postsmeta
YemSalat 2014年

好吧,说实话,无论是调用get_post_meta()它还是将其作为帖子对象,您都需要在每个帖子中对其进行调用。模板标记(例如)也是如此the_content(),您必须在每个帖子中都调用它。
Pieter Goosen 2014年

2
这意味着,如果您必须显示120个帖子,那么您的页面中还会有120个查询?
chifliiiii

所有后置数据都保存在缓存中,因此在计算后置元数据时您将不会有额外的查询
Pieter Goosen

你是对的。我指的是post_thumbnails,但最近发现了update_post_thumbnail_cache($ the_query)。无论如何,感谢您的澄清
chifliiiii

4

这个问题已有1年多的历史了,但是我有同样的问题,这里是将每个meta_value和meta_key添加到$ wp_query对象的函数,

该函数将执行一个额外的查询示例,而不是在while循环中查询每个帖子元。

“从$ wpdb-> postmeta中选择meta_key,meta_value,post_id,在post_id中输入(1,2,3,4,5 ...)”

其中(1,2,3,4,5 ...)从$ wp_query当前查询的帖子ID

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++;
    }
}

我喜欢这个解决方案。
阿姆斯特朗(Armstrongest)

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

首先,我获得带有全局$ wpdb的wordpress数据库功能。然后用$ pt设置posttype。为了获得与post_meta中的特定值匹配的正确帖子,我设置了$ mk(meta_key)

然后设置$ mv(meta_value)变量。(在这种情况下,元值与postid相匹配)

$ mk1- $ mk7是我希望从每个帖子中获取的meta_keys。(我将在select语句中获取值)

我还通过设置$ ord使'order by'为var

select语句如下:我从POST或“ p”中选择帖子ID和post_title。

然后,选择所有需要使用pm1选择的元数据。-> pm.7并获取meta_value并重命名它们(AS),以便从我的对象中检索数据时它更具可读性。

我为需要与帖子匹配的元数据创建了一个LEFT JOIN。(下午)

我为需要检索的每个元数据创建了7个左联接。(pm1-pm7)

WHERE语句基于第一个LEFT JOIN(pm),因此它将知道我只需要元数据匹配的帖子。

我还为帖子类型和非草稿的post_statuses添加了“ AND”。(因此仅发布的帖子)

最后,我添加了“ 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_keymeta_query[]['key']呢?
kaiser 2014年

1
不,这不起作用,并且会返回没有与之关联的帖子数组。
YemSalat 2014年

3
meta_key和/或meta_query不修改返回的结果的类型,仅查询本身。
BODA82
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.