如果您设计或开发WordPress主题或插件,则很有可能在某一天需要对自定义元字段进行查询。这些是您可以附加到任何帖子、页面或自定义帖子类型的完全自定义的键值对。WordPress默认情况下具有基本的UI,或者您可以使用诸如Advanced Custom Fields之类的工具来对其进行高级设置。但在后台,ACF使用的是普通的自定义字段。
您现在正在查看的这个代码片段页面是在1999年编写的。当时,为了查询具有特定自定义字段的帖子,您需要使用`$wpdb`全局变量。它可用于创建WordPress WP_Query()类不支持的MySQL查询。幸运的是,如今WordPress确实提供了一些支持自定义元字段查询的参数。
在这里,我们将介绍您可以请求和循环遍历具有特定自定义字段(及其值)的帖子的不同方法。无论您使用WP_Query
类、query_posts()
还是get_posts()
,您都可以使用此信息。由于query_posts()
和get_posts()
是WP_Query
类的包装器。它们都接受相同的参数。
查询参数
这是一个来自WordPress Codex的WordPress查询基本示例。
<?php
// The Query
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
echo '<ul>';
while ( $the_query->have_posts() ) {
$the_query->the_post();
echo '<li>' . get_the_title() . '</li>';
}
echo '</ul>';
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();
$args
是那里重要的部分。我们将传递不同的参数以使其按我们想要的方式工作。
在查询自定义元数据时,您可以使用两组参数。一组用于简单的自定义元字段查询,另一组用于更复杂的自定义元字段查询。让我们从简单的组开始。
meta_key
meta_key
参数将查询任何已将自定义字段元ID保存到数据库的帖子,无论该字段是否保存了值。meta_key
是您为元字段指定的ID。像这样

此示例将查询任何具有ID为“field1”的自定义元字段的帖子。
$args = array( 'meta_key' => 'field1' );
meta_value
meta_value
参数查询具有您定义的值的帖子。meta_value
参数用于字符串值。此示例将查询任何自定义元字段值为“data1”的帖子。
$args = array( 'meta_value' => 'data1' );
您还可以将两者结合起来。此示例将仅查询具有ID为“field1”且值为“data1”的自定义元字段的帖子。
$args = array(
'meta_key' => 'field1',
'meta_value' => 'data1'
);
meta_value_num
meta_value_num
参数类似于meta_value
参数。meta_value
参数用于字符串值,而meta_value_num
参数用于数值值。
此示例演示了如何在“field1”自定义元字段的值为“10”时对其进行查询。
$args = array(
'meta_key' => 'field1',
'meta_value_num' => '10',
);
meta_compare
meta_compare
参数的功能与其名称完全一致。它允许您将比较运算符与meta_value
和meta_value_num
参数一起使用。您可以使用的比较运算符为‘=’,‘!=’,‘>’,‘>=’,‘<',‘<=’,‘LIKE’,‘NOT LIKE’,‘IN’,‘NOT IN’,‘BETWEEN’,‘NOT BETWEEN’,‘NOT EXISTS’,‘REGEXP’,‘NOT REGEXP’或‘RLIKE’。以下示例演示了如何查询任何不具有“data1”值的帖子。
$args = array(
'meta_key' => 'field1',
'meta_value' => 'data1',
'meta_compare' => '!=',
);
更复杂的查询
meta_query
用于复杂查询的主要参数是meta_query
。此参数本身不执行任何操作。它只是告诉WordPress您要对自定义元字段进行查询。您将在meta_query
中添加其他参数,这些参数将用于定义查询。
key、value和compare
参数key
、value
的工作方式与上面描述的meta-key
、meta-value
完全相同。复杂的compare
类似于上面的简单compare
,但它采用不同的比较运算符列表。复杂的compare
使用‘=’,‘!=’,‘>’,‘>=’,‘<',‘<=’,‘LIKE’,‘NOT LIKE’,‘IN’,‘NOT IN’,‘BETWEEN’,‘NOT BETWEEN’,‘EXISTS’或‘NOT EXISTS’。value
可以是数组,但仅当compare使用‘IN’,‘NOT IN’,‘BETWEEN’或‘NOT BETWEEN’时。
如果您将compare
与‘EXISTS’或‘NOT EXISTS’一起使用,则无需指定value
参数。
以下示例将查询帖子,前提是它具有值为“data1”的“field1”和值为非“data2”的“field2”。
$args = array(
'meta_query' => array(
array(
'key' => 'field1',
'value' => 'data1'
),
array(
'key' => 'field2',
'value' => 'data2',
'compare' => '!=',
)
)
);
relation
当您要使用逻辑关系查询自定义元数据时,使用relation
。您可以使用AND
或OR
。例如,您将使用AND
来比较data1和data2是否满足条件,并且如果data1或data2满足条件,则使用OR
。
此参数是独立的。这意味着它不会出现在单个自定义元字段参数中。让我们看一个例子。此示例将仅查询具有值为“data1”的“field1”和值为“data2”的“field2”的帖子。
$args = array(
'meta_query' => array(
'relation' => 'AND'
array(
'key' => 'field1',
'value' => 'data1',
),
array(
'key' => 'field2',
'value' => 'data2',
),
)
);
如果您将relation
更改为“OR”。然后它将查询任何帖子,前提是“field1”的值为“data1”,或者“field2”的值为“data2”。
type
type
参数允许您选择要查询的数据类型。您可以使用‘NUMERIC’,‘BINARY’,‘CHAR’,‘DATE’,‘DATETIME’,‘DECIMAL’,‘SIGNED’,‘TIME’或‘UNSIGNED’。
仅当日期格式为“YYYYMMDD”时,才能将“DATE”类型与compare
“BETWEEN”一起使用。
此示例将查询任何“field1”的值为数值的帖子。
$args = array(
'meta_query' => array(
array(
'key' => 'field1',
'value' => 'data1',
'type' => 'NUMERIC'
)
)
);
真实世界示例
到目前为止,我仅提供了使用任意数据和字段的示例。现在,我想向您展示一个查询自定义元字段的真实世界示例。
场景
您创建了一个事件自定义帖子类型。事件帖子类型具有一个日期自定义字段,其 ID 为 event_date
。您希望创建一个查询,显示将在当前日期到未来 30 天内开始的任何事件。
我们将使用 meta_query
参数,因为我们希望使用 type
参数将“event_date”字段定义为“DATE”数据类型。
这是查询
$args = array(
'post_type' => 'post',
'posts_per_page' => -1,
'post_status' => 'publish',
'meta_query' => array(
array(
'key' => 'event_date',
'value' => array( date( 'Ymd', strtotime( '-1 day' ) ), date( 'Ymd', strtotime( '+31 days' ) ) ),
'compare' => 'BETWEEN',
'type' => 'DATE'
)
)
);
$event_query = new WP_Query( $args );
value
是当前日期减 1 天和当前日期加 31 天的数组。由于我们使用的是比较器“BETWEEN”,因此只会查询 value 数组之间的帖子,因此我们希望将它们偏移一天。
使用此查询,您将显示未来 30 天内发生的任何事件。
结论
WP_Query
类是一个非常灵活的类,它允许您创建大量自定义查询。如果您想了解有关查询可以使用的不同参数的更多信息,我建议您查看WP_Query
手册页面。
这很棒!如果您想将循环限制为 5 个帖子/页面怎么办?
好的,这很容易。只需将 LIMIT 4 添加到查询详细信息中……
嗯..它支持 WordPress 2.9 吗???
很棒的东西,在我的一个 wp 模板中的多个地方使用它。
此外,是否有一种方法可以查询多个自定义字段并打印“合并”的结果?
这与使用 wp_query 获得的结果不是一样吗?
像这样
http://wordpress.pastebin.com/uJDdsiCw
我使用了此参考
http://codex.wordpress.org/Template_Tags/query_posts#Custom_Field_Parameters
但还没有尝试过。
它实际上可以。我刚刚这样使用了。
无论是因为新手还是没有理解在哪里放置,我都无法实现文章中的代码。
我得到了你的代码并将其与一个更简单的查询集成在一起;
$loop = new WP_Query( $args );
if($loop->have_posts()): while ( $loop->have_posts() ) : $loop->the_post();
这是一个完成此任务的更简单的方法。http://pastie.org/2464333 它每次都能完美运行!
使用 SQL 查询的灵活性大于自定义帖子查询。例如,如果您想在一个范围内搜索或类似的东西。
我一直试图弄清楚,如何显示特定类别的帖子,如果正在查看的页面模板具有相同名称的自定义字段值。
即,存在自定义字段值,并且显示与该自定义字段值同名的类别中的帖子。
我正在尝试使用它来输出特定父页面的子页面,这些子页面具有特定的自定义字段。问题是它会输出多个相同的子页面,具体取决于为自定义字段声明了多少个值。也就是说,如果子页面有两个不同的“soundfile”自定义字段值,它将输出该子页面两次。我该如何限制它。这是我正在处理的页面的链接
http://www.oliviablock.net/listen/
提前感谢
好的,通过某种奇迹,我能够找出上述评论的解决方案。我没有使用 OBJECT,而是使用了 OBJECT_K,它将输出结果作为行对象的关联数组,使用第一列的值作为键,以便丢弃重复项。
谢谢,
carol
感谢 Chris!!!你用这个救了我的命!:)
太棒了!这对我来说就像一个魅力,非常感谢!
非常不错,Chris。这给了我所需的控制权,可以输出我的主页上的帖子内容。干杯,伙计。
我想感谢你发表这篇超级有用的帖子。它基本上拯救了我的生命。我花了太多时间尝试使用 WordPress 内置查询做类似的事情,但一直无法做到。
谢谢!
非常好的帖子,Chris,我几乎以为它可以解决我遇到的问题,我到处都查找过相关信息,但找不到解决方案。我希望这里有人会对如何做到这一点有一些想法,或者它是否可能。
以下是本文代码的一部分,我的自定义字段称为“views”,通过使用 wp-postviews 插件,该自定义字段被赋予查看该帖子的用户数量。是否有任何方法可以获取最后一行,而不是按日期排序帖子,而是按自定义字段查看次数值(降序)排序?我几乎放弃了尝试,所以如果有人知道,我将不胜感激!
$querydetails = ”
SELECT wposts.*
FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta
WHERE wposts.ID = wpostmeta.post_id
AND wpostmeta.meta_key = ‘views’
AND wposts.post_status = ‘publish’
AND wposts.post_type = ‘post’
ORDER BY wposts.post_date DESC
更新一下,其他人很乐意更新我当前的代码(不是上面的代码)以按查看次数排序帖子。只是想分享一下,以防有人想做同样的事情。
这是一篇很棒的帖子!
使用此脚本,基于自定义字段,WordPress 更加灵活。
谢谢!你救了我的工作。:)
我知道这是一年前的帖子,但我一直在寻找我问题的解决方案,但我还没有找到解决方案。
从代码方面来说,我正在使用您发布的完全相同的代码。但是,查询仅检索一个结果。
任何想法是什么导致了这种情况?
提前感谢!
我无法更改循环查询
代码
我如何修改
它通过自定义字段..
和查询
请任何人都帮助我……。
实际上,我必须在查询中实现 where 和 like 条件。
用于按特定值搜索
好吧,确实是一个旧帖子,但我希望实现相同的查询,但有多个条件。类似这样
您正在寻找这个技巧。
嗨,Chris
我正要使用这段代码时,我发现我认为是一个小错误。
在这一行
我认为在第一个 PHP 代码段之后多了一个“>”。div 标签过早结束。
精彩的文章!解决了自定义字段的 SQL 问题。
谢谢!
谢谢..很棒的教程,非常有帮助。
运行良好,非常感谢!:-)
运行良好:) 谢谢分享
很棒…(顺便说一句,这个网站上的很多设计也很棒!)
一个问题… wpostmeta.meta_value 是否有“通配符”选项?
基本上,如果我选择的 meta_key 中没有数据,我想隐藏循环,但只要其中有某些内容,我就想让它显示出来…
变量太多了(并且偶尔会添加更多),因此使用硬编码数组是不可行的…
我尝试过 $key,只要有值它就能正常工作,但是当没有值时,它实际上会显示两次查询输出(没有数据)…
我正在尝试使用它来创建自定义日历,但由于我在这方面是新手,所以我有点迷茫。我知道我需要使用上面的代码来提取日期的元数据。但是在日历的特定日期内发布标题和永久链接对我来说超出了我的能力范围。我知道我可以提取标题和永久链接并像上面一样显示,但是如何才能使其在日历的正确日期框中显示?有没有人有什么想法?
PS:就像我上面说的,我在这方面是新手,所以我一边学习一边尝试解决问题。请原谅我的无知。
为什么不使用这段代码呢?
我将不得不为此使用一个非常奇怪的归档布局,我被要求构建它;有人知道如何使用 WordPress 的内置分页来处理这些结果吗?我知道我可以在 SQL 中使用 OFFSET 和 LIMIT 并手动执行此操作,但我理想情况下希望在可能的情况下挂接到默认的 WordPress 实现。
好东西!一直在用它来进行大量查询!谢谢。
大家好。
我需要检查两个元键和元值。如果找到任何元键和元值,则获取帖子和相关的元数据。
例如
where ( wpostmeta.meta_key = ‘any’
AND wpostmeta.meta_value = ‘any’)
或
( wpostmeta.meta_key = ‘another’
AND wpostmeta.meta_value = ‘another’),
请帮忙,抱歉我的英语不好。
大家好。
我需要检查两个元键和元值。如果找到任何元键和元值,则获取帖子和相关的元数据。
例如
或
请帮忙,抱歉我的英语不好。
对于那些不想修改代码的人,通过 高级帖子类型排序 插件有一个非常简单的解决方案,更多详细信息请访问 http://www.nsp-code.com/how-to-order-wordpress-posts-using-a-custom-field-value/<a/>
关于这个问题。我理解在使用 wp_query 时,元数据和其他好东西会被缓存。使用此查询会失去这些速度优势吗?
现在我可以编写自定义查询来显示我想要在我的自定义循环中显示的帖子元数据了。你太棒了 :)
这里有一些不错的技巧,但我试图让自定义字段等于页面标题,这样我就可以让许多页面使用相同的循环。
谢谢分享这段代码!你让我的一天变得美好!
谢谢,完美运行! :)
令人惊讶的是,MIN() & GROUP BY 可以工作,并且我能够通过下面的“SQL”获得我想要的结果,但遇到了一些问题。
现在我想访问每个 p.ID 的单个 MIN(pm.meta_value) 作为日期。这是一个至关重要的信息,我不知道如何在结果循环中将其返回。
嗨,好东西。有趣的文章,但我认为为了这篇文章的缘故,你必须使用 GROUP BY 子句以避免获取重复的行。
由于你使用 SQL 而不是 WP_Query 进行查询,因此添加分页内容也很有用。
我认为这样效果会更好
SELECT wposts.*
FROM posts wposts,postmeta wpostmeta
WHERE wposts.ID = wpostmeta.post_id
AND wposts.post_status = ‘publish’
AND wposts.post_type = ‘post’
GROUP BY wposts.ID
ORDER BY wposts.post_date DESC;
我在 http://www.glocalmart.it 上使用了它,在那里我只是尝试通过查询(不使用 WP_Query)来满足搜索表单的需求。
谢谢。
这确实应该重定向到帖子 v.3.2 标准,你有没有关于元查询的教程?
http://codex.wordpress.org/Class_Reference/WP_Meta_Query
整个事情都应该通过查询系统来完成,而不是自定义的 select 语句。
我在 Genesis 自定义模板中显示自定义字段时遇到问题,无法解决!
我想能够设置字段的样式,并且我还在使用自定义类来设置布局的样式!
我无法弄清楚如何将这些字段添加到内容区域。我之前能够使用 Genesis 中的 PHP 添加这些字段,但现在使用 Execute-Pro 主题时无法工作。
这是我想添加到页面模板内容区域的代码。http://codepen.io/anon/pen/RPGqNb.html
很棒的文章,只是一点观察;
relation’ => ‘AND’
在结束的 ‘?’ 之后不应该有一个逗号吗?如果没有,它会使网站崩溃吗?
Simon 说得对。我遇到了同样的问题。应该有一个逗号,否则会导致语法错误。除此之外,很棒的东西。非常有帮助。
很酷的信息。对初学者非常有用
嗨,我想触发这样的查询,这可能吗?因为表中的日期是字符串格式“2016年1月20日”这样的格式,我想根据日期过滤日期,所以这可能吗?请告诉我。
$query_args[‘meta_query’][] = array(
‘DATE(key)’ => ‘_start_date’,
‘value’ => array($end_date, $start_date),
‘compare’ => ‘BETWEEN’,
‘type’ => ‘date’,
);
OR
$query_args[‘meta_query’][] = array(
‘key’ => ‘DATE(_start_date)’,
‘value’ => array($end_date, $start_date),
‘compare’ => ‘BETWEEN’,
‘type’ => ‘date’,
);
谢谢。
很棒的文章。清晰、简洁且非常有帮助。谢谢!!
嗨,Chris,
精彩的文章!我正在尝试查询“产品”帖子类型中的帖子,这些帖子与循环中来自“项目”帖子类型的当前帖子匹配,基于自定义字段“product-ean”和“item-ean”。
例如:我有一个“项目”帖子,其“item-ean”为 123,以及两个“产品”帖子,其“product-ean”为 123。现在我想在“项目”帖子中显示这两个“产品”帖子。
非常感谢您的帮助,谢谢。