ОБНОВЛЕНИЕ 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
действие вызывалось дважды: один раз над таблицей 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 Refactor
Поскольку я в восторге от PHP 7, на случай, если вы используете WP на сервере PHP 7, вот более короткая и сексуальная версия с использованием оператора??
объединения нулей :
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' );
Наслаждайтесь!