2 pre_get_posts 个函数以按自定义字段过滤
2 pre_get_posts functions to filter by custom fields
编辑:查看最后一个(第 3 个)代码片段,它是有效的。
我有一个 "Actions" 页面(一个名为 Actions 的自定义 post 类型的存档),它等同于 "events".
我使用 this tutorial 使用自定义字段过滤它们:ville(城市)、action(动作类型)和日期,效果非常好。
然后我创建了另一个函数来过滤 "date range":过去、未来的操作。它也有效。但是他们"accumulate"。当我 select "Past" 行动和一个城市时,它会显示所有过去的行动 + 所有在城市中发生或将要发生的行动。
所以这两个函数可以工作,但我不知道如何将它们的关系设置为 AND 或使它们一起工作的东西而不是 "accumulating"。
有人可以帮我解决这个问题吗?
谢谢。
按 Type/City/Date 自定义字段过滤的函数:
// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array(
'action' => 'action',
'ville' => 'ville',
'date' => 'date',
);
// action
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
// get meta query
$meta_query = $query->get('meta_query');
// loop over filters
foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
// continue if not found in url
if( empty($_GET[ $name ]) ) {
continue;
}
// get the value for this filter
// eg: http://www.website.com/events?city=melbourne,sydney
$value = explode(',', $_GET[ $name ]);
// append meta query
$meta_query[] = array(
'key' => $name,
'value' => $value,
'compare' => 'IN',
);
}
$query->set( 'orderby', array( 'date' => 'DESC' ) );
// update meta query
$query->set('meta_query', $meta_query);
return;
}
?>
Future/Past 操作的函数:
<?php
add_action('pre_get_posts', 'future_past_actions', 10, 1);
function future_past_actions( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
// get meta query
$meta_query = $query->get('meta_query');
if( isset($_GET['range']) ) {
$range = explode(',', $_GET['range']);
$meta_query[] = array(
'key' => 'range',
'value' => $range,
'compare' => 'IN',
);
if( $query->get( 'range' ) == 'future' ) {
$meta_query[] = array(
'key' => 'date',
'value' => date("Ymd"),
'compare' => '>',
);
$meta_query['relation'] = 'OR';
}
elseif( $query->get( 'range' ) == 'past' ) {
$meta_query[] = array(
'key' => 'date',
'value' => date("Ymd"),
'compare' => '<',
);
$meta_query['relation'] = 'OR';
}
elseif( $query->get( 'range' ) == 'toutes' ) {
return;
}
}
$query->set( 'meta_key', 'date' );
$query->set( 'orderby', array( 'date' => 'DESC' ) );
$query->set('meta_query', $meta_query);
return;
}
?>
最终合并后的工作代码:
<?php
// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array(
'action' => 'action',
'ville' => 'ville',
'date' => 'date'
);
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
if( ! is_post_type_archive( 'actions' ) ) return;
// CITY/TYPE/DATE filters
// loop over filters
foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
// continue if not found in url
if( empty($_GET[ $name ]) ) { continue; }
// get the value for this filter
// eg: http://www.website.com/events?city=melbourne,sydney
$value = explode(',', $_GET[ $name ]);
// append meta query
$meta_query[] = array(
'key' => $name,
'value' => $value,
'compare' => 'IN',
);
}
// FUTURE/PAST/ALL filters
if( isset($_GET['range']) ) {
$range = $_GET['range'];
if($range != "toutes") {
// Select what kind of compare you need
if($range == "past") {
$comparer = '<';
} else if($range == "future") {
$comparer = '>=';
}
// If you need to filter by date add this to meta_query array
$meta_query[] = array(
'key' => 'date',
'value' => date("Ymd"),
'compare' => $comparer,
);
}
}
// update meta query
$query->set('meta_query', $meta_query);
$query->set( 'meta_key', 'date' );
$query->set( 'orderby', array( 'date' => 'DESC' ) );
$query->set('posts_per_page', '20');
}
?>
在这种情况下,我认为最好的解决方案是执行一个操作并检查其中的查询参数,然后决定要执行哪种逻辑。
$query 变量包含您分配的所有参数,因此您的代码可能如下所示:
考虑到对情况的评论进行编辑,您必须在两个元字段之间使用 AND 关系。动作中的代码应如下所示:
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
$meta_query = array(
'relation' => 'AND',
array(
'key' => 'ville',
'value' => '$value',
'compare' => '=',
)
);
// Select what kind of compare you need
if($range == "past") {
$compare = ">";
} else if($range == "future") {
$compare = "<";
}
if($range != "all") {
// If you need to filter by date add this to meta_query array
$date_query = array(
'key' => 'date',
'value' => 'date(\"Ymd\"),',
'compare' => $compare,
);
$meta_query[] = $date_query;
}
$query->set( 'orderby', array( 'date' => 'DESC' ) );
// update meta query
$query->set('meta_query', $meta_query);
}
因为您现在所做的是多次设置查询参数。
如果您需要更多参数来过滤掉,您可以根据获得的参数类型有条件地将它们添加到 $meta_query 变量中。
我想如果我理解正确的话,这种元查询应该 return 需要结果。
编辑:查看最后一个(第 3 个)代码片段,它是有效的。
我有一个 "Actions" 页面(一个名为 Actions 的自定义 post 类型的存档),它等同于 "events".
我使用 this tutorial 使用自定义字段过滤它们:ville(城市)、action(动作类型)和日期,效果非常好。
然后我创建了另一个函数来过滤 "date range":过去、未来的操作。它也有效。但是他们"accumulate"。当我 select "Past" 行动和一个城市时,它会显示所有过去的行动 + 所有在城市中发生或将要发生的行动。
所以这两个函数可以工作,但我不知道如何将它们的关系设置为 AND 或使它们一起工作的东西而不是 "accumulating"。
有人可以帮我解决这个问题吗?
谢谢。
按 Type/City/Date 自定义字段过滤的函数:
// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array(
'action' => 'action',
'ville' => 'ville',
'date' => 'date',
);
// action
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
// get meta query
$meta_query = $query->get('meta_query');
// loop over filters
foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
// continue if not found in url
if( empty($_GET[ $name ]) ) {
continue;
}
// get the value for this filter
// eg: http://www.website.com/events?city=melbourne,sydney
$value = explode(',', $_GET[ $name ]);
// append meta query
$meta_query[] = array(
'key' => $name,
'value' => $value,
'compare' => 'IN',
);
}
$query->set( 'orderby', array( 'date' => 'DESC' ) );
// update meta query
$query->set('meta_query', $meta_query);
return;
}
?>
Future/Past 操作的函数:
<?php
add_action('pre_get_posts', 'future_past_actions', 10, 1);
function future_past_actions( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
// get meta query
$meta_query = $query->get('meta_query');
if( isset($_GET['range']) ) {
$range = explode(',', $_GET['range']);
$meta_query[] = array(
'key' => 'range',
'value' => $range,
'compare' => 'IN',
);
if( $query->get( 'range' ) == 'future' ) {
$meta_query[] = array(
'key' => 'date',
'value' => date("Ymd"),
'compare' => '>',
);
$meta_query['relation'] = 'OR';
}
elseif( $query->get( 'range' ) == 'past' ) {
$meta_query[] = array(
'key' => 'date',
'value' => date("Ymd"),
'compare' => '<',
);
$meta_query['relation'] = 'OR';
}
elseif( $query->get( 'range' ) == 'toutes' ) {
return;
}
}
$query->set( 'meta_key', 'date' );
$query->set( 'orderby', array( 'date' => 'DESC' ) );
$query->set('meta_query', $meta_query);
return;
}
?>
最终合并后的工作代码:
<?php
// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array(
'action' => 'action',
'ville' => 'ville',
'date' => 'date'
);
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
if( ! is_post_type_archive( 'actions' ) ) return;
// CITY/TYPE/DATE filters
// loop over filters
foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
// continue if not found in url
if( empty($_GET[ $name ]) ) { continue; }
// get the value for this filter
// eg: http://www.website.com/events?city=melbourne,sydney
$value = explode(',', $_GET[ $name ]);
// append meta query
$meta_query[] = array(
'key' => $name,
'value' => $value,
'compare' => 'IN',
);
}
// FUTURE/PAST/ALL filters
if( isset($_GET['range']) ) {
$range = $_GET['range'];
if($range != "toutes") {
// Select what kind of compare you need
if($range == "past") {
$comparer = '<';
} else if($range == "future") {
$comparer = '>=';
}
// If you need to filter by date add this to meta_query array
$meta_query[] = array(
'key' => 'date',
'value' => date("Ymd"),
'compare' => $comparer,
);
}
}
// update meta query
$query->set('meta_query', $meta_query);
$query->set( 'meta_key', 'date' );
$query->set( 'orderby', array( 'date' => 'DESC' ) );
$query->set('posts_per_page', '20');
}
?>
在这种情况下,我认为最好的解决方案是执行一个操作并检查其中的查询参数,然后决定要执行哪种逻辑。
$query 变量包含您分配的所有参数,因此您的代码可能如下所示:
考虑到对情况的评论进行编辑,您必须在两个元字段之间使用 AND 关系。动作中的代码应如下所示:
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
$meta_query = array(
'relation' => 'AND',
array(
'key' => 'ville',
'value' => '$value',
'compare' => '=',
)
);
// Select what kind of compare you need
if($range == "past") {
$compare = ">";
} else if($range == "future") {
$compare = "<";
}
if($range != "all") {
// If you need to filter by date add this to meta_query array
$date_query = array(
'key' => 'date',
'value' => 'date(\"Ymd\"),',
'compare' => $compare,
);
$meta_query[] = $date_query;
}
$query->set( 'orderby', array( 'date' => 'DESC' ) );
// update meta query
$query->set('meta_query', $meta_query);
}
因为您现在所做的是多次设置查询参数。 如果您需要更多参数来过滤掉,您可以根据获得的参数类型有条件地将它们添加到 $meta_query 变量中。
我想如果我理解正确的话,这种元查询应该 return 需要结果。