更新2018-06-28
尽管下面的代码通常可以正常工作,但这是WP> = 4.6.0的代码的重写(使用PHP 7):
function add_course_section_filter( $which ) {
// create sprintf templates for <select> and <option>s
$st = '<select name="course_section_%s" style="float:none;"><option value="">%s</option>%s</select>';
$ot = '<option value="%s" %s>Section %s</option>';
// determine which filter button was clicked, if any and set section
$button = key( array_filter( $_GET, function($v) { return __( 'Filter' ) === $v; } ) );
$section = $_GET[ 'course_section_' . $button ] ?? -1;
// generate <option> and <select> code
$options = implode( '', array_map( function($i) use ( $ot, $section ) {
return sprintf( $ot, $i, selected( $i, $section, false ), $i );
}, range( 1, 3 ) ));
$select = sprintf( $st, $which, __( 'Course Section...' ), $options );
// output <select> and submit button
echo $select;
submit_button(__( 'Filter' ), null, $which, false);
}
add_action('restrict_manage_users', 'add_course_section_filter');
function filter_users_by_course_section($query)
{
global $pagenow;
if (is_admin() && 'users.php' == $pagenow) {
$button = key( array_filter( $_GET, function($v) { return __( 'Filter' ) === $v; } ) );
if ($section = $_GET[ 'course_section_' . $button ]) {
$meta_query = [['key' => 'courses','value' => $section, 'compare' => 'LIKE']];
$query->set('meta_key', 'courses');
$query->set('meta_query', $meta_query);
}
}
}
add_filter('pre_get_users', 'filter_users_by_course_section');
我结合了@birgire和@cale_b的一些想法,这些想法还提供了以下值得阅读的解决方案。具体来说,我:
- 使用了
$which
添加到的变量v4.6.0
- 通过使用可翻译字符串(例如,i18n)使用了最佳实践
__( 'Filter' )
- 交换循环的(更时尚呢?)
array_map()
,array_filter()
和range()
- 用于
sprintf()
生成标记模板
- 使用方括号数组表示法代替
array()
最后,我在较早的解决方案中发现了一个错误。这些解决方案总是青睐顶部<select>
在底部<select>
。因此,如果您从顶部下拉菜单中选择了一个过滤器选项,然后又从底部下拉菜单中选择了一个,则过滤器仍将仅使用顶部的任何值(如果不为空)。此新版本纠正了该错误。
更新2018-02-14
自WP 4.6.0起已修复此问题,更改已记录在正式文档中。不过,下面的解决方案仍然有效。
导致问题的原因(WP <4.6.0)
问题在于该restrict_manage_users
动作被调用了两次:一次在“用户”表上方,一次在“表”下方。这意味着将select
创建两个具有相同名称的下拉菜单。Filter
单击该按钮时,第二个select
元素中的任何值(即表下方的值)都会覆盖第一个元素中的值,即表上方的值。
如果您想深入了解WP源,restrict_manage_users
则从内部触发该操作WP_Users_List_Table::extra_tablenav($which)
,该功能可创建本机下拉菜单来更改用户角色。该函数借助$which
变量的帮助,该变量告诉它是创建select
表单的上方还是下方,并允许其为两个下拉菜单提供不同的name
属性。不幸的是,$which
变量没有传递给restrict_manage_users
操作,因此我们必须想出另一种方式来区分我们自己的自定义元素。
如@Linnea所建议的,执行此操作的一种方法是添加一些JavaScript来捕获Filter
单击并同步两个下拉列表的值。我选择了现在将要描述的纯PHP解决方案。
如何修复
您可以利用将HTML输入转换为值数组,然后过滤该数组以除去所有未定义值的功能。这是代码:
function add_course_section_filter() {
if ( isset( $_GET[ 'course_section' ]) ) {
$section = $_GET[ 'course_section' ];
$section = !empty( $section[ 0 ] ) ? $section[ 0 ] : $section[ 1 ];
} else {
$section = -1;
}
echo ' <select name="course_section[]" style="float:none;"><option value="">Course Section...</option>';
for ( $i = 1; $i <= 3; ++$i ) {
$selected = $i == $section ? ' selected="selected"' : '';
echo '<option value="' . $i . '"' . $selected . '>Section ' . $i . '</option>';
}
echo '</select>';
echo '<input type="submit" class="button" value="Filter">';
}
add_action( 'restrict_manage_users', 'add_course_section_filter' );
function filter_users_by_course_section( $query ) {
global $pagenow;
if ( is_admin() &&
'users.php' == $pagenow &&
isset( $_GET[ 'course_section' ] ) &&
is_array( $_GET[ 'course_section' ] )
) {
$section = $_GET[ 'course_section' ];
$section = !empty( $section[ 0 ] ) ? $section[ 0 ] : $section[ 1 ];
$meta_query = array(
array(
'key' => 'course_section',
'value' => $section
)
);
$query->set( 'meta_key', 'course_section' );
$query->set( 'meta_query', $meta_query );
}
}
add_filter( 'pre_get_users', 'filter_users_by_course_section' );
奖励:PHP 7重构
由于我对PHP 7感到很兴奋,以防万一您在PHP 7服务器上运行WP,因此这是一个使用null合并运算符??
的简短而性感的版本:
function add_course_section_filter() {
$section = $_GET[ 'course_section' ][ 0 ] ?? $_GET[ 'course_section' ][ 1 ] ?? -1;
echo ' <select name="course_section[]" style="float:none;"><option value="">Course Section...</option>';
for ( $i = 1; $i <= 3; ++$i ) {
$selected = $i == $section ? ' selected="selected"' : '';
echo '<option value="' . $i . '"' . $selected . '>Section ' . $i . '</option>';
}
echo '</select>';
echo '<input type="submit" class="button" value="Filter">';
}
add_action( 'restrict_manage_users', 'add_course_section_filter' );
function filter_users_by_course_section( $query ) {
global $pagenow;
if ( is_admin() && 'users.php' == $pagenow) {
$section = $_GET[ 'course_section' ][ 0 ] ?? $_GET[ 'course_section' ][ 1 ] ?? null;
if ( null !== $section ) {
$meta_query = array(
array(
'key' => 'course_section',
'value' => $section
)
);
$query->set( 'meta_key', 'course_section' );
$query->set( 'meta_query', $meta_query );
}
}
}
add_filter( 'pre_get_users', 'filter_users_by_course_section' );
请享用!