使用高级自定义字段按自定义字段查询帖子
高级自定义字段 显然是一个很棒的插件,但是它的 API 有一两件事可以变得更容易。
例如,在普通 ACF 中,没有简单的方法可以从字段名称中获取字段对象,尽管 文件说. 这 get_field_object
如果按名称查询,则仅返回部分信息 – 要返回您需要使用字段键的完整对象。 (旁注:在 ACF Pro 中它更容易一些,因为您可以使用 acf_get_field
函数 做 返回完整的字段对象。)
如果您在自己创建字段的单个已知站点上进行开发,那很好。 但是,如果您正在开发使用 ACF 的主题或插件,您不知道密钥,而找到它们的唯一方法是 相当复杂.
另一个问题是根据自定义字段值选择帖子。
单值字段
基于简单的单值字段(例如“数字”或“文本”)选择帖子非常简单。 您只需使用标准 WP_Meta_Query
字段。 我不会在这里重述这些内容,但您可以阅读文档了解详细信息。
示例查询
假设我们根据两个自定义字段选择帖子 – email
和 num_articles
. 我们要选择邮件为 [email protected] 且文章数量大于 1 的所有帖子:
$args = array( 'post_type' => 'post', 'meta_query' => array( 'relation' => 'AND', array( 'key' => 'email', 'value' => '[email protected]', 'compare' => '=' ), array( 'key' => 'num_articles', 'value' => 1, 'type' => 'NUMERIC', 'compare' => '>' ) ) ); $posts = get_posts( $args ); // etc...
这一切都很简单,与没有 ACF 的自定义字段查询没有什么不同。
基于数组的字段
但是,当使用基于数组的字段(例如复选框)或允许多选的字段时,它会变得更加复杂。
文档说你应该使用 LIKE 运算符 对于这些领域,乍一看是有道理的。
考虑一个复选框字段(字段名称: checkbox_field
)。 具有此字段的帖子将在 wp_post_meta
看起来像:
meta_id | post_id | 元密钥 | 元值 |
---|---|---|---|
1 | 123 | 复选框字段 | a:2:{i:0;s:3:”一个”;i:1;s:5:”三个”;} |
这 meta_value
column 是我们感兴趣的位。由于这是一个基于数组的字段,因此 value 是一个序列化数组。 所以在这种情况下,我们有一个长度为 2 的数组,其中包含两个值: 一 和 三.
示例查询
使用 LIKE 运算符根据此字段选择帖子可能如下所示:
$args = array( 'post_type' => 'post', 'meta_query' => array( array( 'key' => 'checkbox_field', 'value' => 'three', 'compare' => 'LIKE' ) ) ); $posts = get_posts( $args ); // etc...
在这种情况下,一切正常。
另一个例子
但是,考虑一个允许多部分的用户字段:
包含此字段的帖子将有一个 user_field
价值在 wp_post_meta
看起来像:
meta_id | post_id | 元密钥 | 元值 |
---|---|---|---|
2 | 123 | 用户字段 | a:1:{i:0;s:1:”2″;} |
3 | 125 | 用户字段 | a:2:{i:0;s:1:”3″;i:1;s:2:”11″} |
4 | 127 | 用户字段 | a:1:{i:0;s:1:”4″;} |
因此,在这种情况下,这些值存储为包含用户 ID 的数组。
意想不到的结果
使用此字段的查询可能如下所示:
$args = array( 'post_type' => 'post', 'meta_query' => array( array( 'key' => 'user_field', 'value' => '2', 'compare' => 'LIKE' ) ) ); $posts = get_posts( $args ); // etc...
然而,这会产生意想不到的结果。 由于这些值是序列化数组,因此上述查询将匹配 2 个帖子 – 123 和 125 – 因为两者都包含字符串“2”。 第一个 (post_id = 123) 是正确的,因为“2”指的是我们正在寻找的用户 ID。 但是第二个结果是获取序列化的字符串引用“s:2”,我们绝对不希望在结果中出现这种情况。
改进查询
一种基于数组值选择帖子的改进方法需要考虑到这一点。 这 WP_Meta_Query 的文档 提到(从 3.7 开始)它支持 SQL 运算符,例如“REGEXP”和“NOT REGEXP”。 这可以用来改进上面示例中的字段选择,生成如下所示的内容:
$args = array( 'post_type' => 'post', 'meta_query' => array( array( 'key' => 'user_field', 'value' => '^2$|s:1:"2";', 'compare' => 'REGEXP' ) ) ); $posts = get_posts( $args ); // etc...
现在将返回正确数量的帖子,因为它考虑了序列化格式。 如果字段存储为单个值(例如,如果您将字段从多选切换到单选),我们还有一个替代选项。
要从变量字段值自动生成此查询,您可以使用以下代码:
$search_value="xyz"; // whatever $field_value = sprintf( '^%1$s$|s:%2$u:"%1$s";', $search_value, strlen( $search_value ) ); $args = array( 'post_type' => 'post', 'meta_query' => array( array( 'key' => 'user_field', 'value' => $field_value, 'compare' => 'REGEXP' ) ) ); // etc...
您显然可以将其与其他元查询结合使用,以基于多个字段选择帖子 AND
或者 OR
运营商。
结论
目前,这是我所知道的在基于数组的字段中搜索的最佳方法。 WP 或 ACF 中没有本地方式,但如果您知道更好的方式,请在下面的评论中分享。 如果您对此有任何其他意见或改进,请告诉我。