Проблема
WP, кажется, удаляет значение моей переменной запроса, прежде чем он будет использован для фильтрации списка пользователей.
Мой код
Эта функция добавляет пользовательский столбец в мою таблицу Users /wp-admin/users.php
:
function add_course_section_to_user_meta( $columns ) {
$columns['course_section'] = 'Section';
return $columns;
}
add_filter( 'manage_users_columns', 'add_course_section_to_user_meta' );
Эта функция сообщает WP, как заполнять значения в столбце:
function manage_users_course_section( $val, $col, $uid ) {
if ( 'course_section' === $col )
return get_the_author_meta( 'course_section', $uid );
}
add_filter( 'manage_users_custom_column', 'manage_users_course_section' );
Это добавляет выпадающий список и Filter
кнопку над таблицей Users:
function add_course_section_filter() {
echo '<select name="course_section" style="float:none;">';
echo '<option value="">Course Section...</option>';
for ( $i = 1; $i <= 3; ++$i ) {
if ( $i == $_GET[ 'course_section' ] ) {
echo '<option value="'.$i.'" selected="selected">Section '.$i.'</option>';
} else {
echo '<option value="'.$i.'">Section '.$i.'</option>';
}
}
echo '<input id="post-query-submit" type="submit" class="button" value="Filter" name="">';
}
add_action( 'restrict_manage_users', 'add_course_section_filter' );
Эта функция изменяет пользовательский запрос, чтобы добавить мой meta_query
:
function filter_users_by_course_section( $query ) {
global $pagenow;
if ( is_admin() &&
'users.php' == $pagenow &&
isset( $_GET[ 'course_section' ] ) &&
!empty( $_GET[ 'course_section' ] )
) {
$section = $_GET[ 'course_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' );
Другая информация
Это создает мой выпадающий правильно. Когда я выбираю раздел курса и щелкаю Filter
страницу, она обновляется и course_section
отображается в URL, но она не имеет значения, связанного с ним. Если я проверяю HTTP-запросы, это показывает, что они отправляются с правильным значением переменной, но затем есть такая, 302 Redirect
которая, кажется, удаляет выбранное мной значение.
Если я отправлю course_section
переменную, введя ее непосредственно в URL, фильтр будет работать как положено.
Мой код примерно основан на этом коде от Дейва Корта .
Я также попытался внести в белый список мой запрос var, используя этот код, но безуспешно:
function add_course_section_query_var( $qvars ) {
$qvars[] = 'course_section';
return $qvars;
}
add_filter( 'query_vars', 'add_course_section_query_var' );
Я использую WP 4.4. Есть идеи, почему мой фильтр не работает?
Ответы:
ОБНОВЛЕНИЕ 2018-06-28
В то время как приведенный ниже код в основном работает нормально, приведем переписывание кода для WP> = 4.6.0 (с использованием PHP 7):
Я включил несколько идей от @birgire и @cale_b, которые также предлагают ниже решения, которые стоит прочитать. В частности, я:
$which
переменную, которая была добавлена вv4.6.0
__( '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 в массивы значений, а затем фильтровать массив, чтобы избавиться от любых неопределенных значений. Вот код:
Бонус: PHP 7 Refactor
Поскольку я в восторге от PHP 7, на случай, если вы используете WP на сервере PHP 7, вот более короткая и сексуальная версия с использованием оператора
??
объединения нулей :Наслаждайтесь!
источник
</select>
я также нашел, чтобы заставить его работать, который я должен был поместить<form method="get">
перед меню выбора и</form>
после кнопки фильтра.</select>
теги! Я добавил их. Странно, что вам нужно было обернуть его,<form>
поскольку вся эта страница обернута в одну большую форму, и этот код вставляется в ее середину. Рад, что у вас все получилось. :)В основном нижние входные имена помечены номером экземпляра, например
new_role
(вверху) иnew_role2
(внизу). Вот два подхода к подобному соглашению об именах, а именноcourse_section1
(вверху) иcourse_section2
(внизу):Подход № 1
Поскольку
$which
переменная ( top , bottom ) не передается вrestrict_manage_users
ловушку, мы можем обойти это, создав собственную версию этой ловушки:Давайте создадим хук действия,
wpse_restrict_manage_users
который имеет доступ к$which
переменной:Тогда мы можем подключить это с:
где мы теперь ,
$name
какcourse_section1
в верхней , иcourse_section2
в нижней части .Подход № 2
Давайте рассмотрим
restrict_manage_users
выпадающие списки с разными именами для каждого экземпляра:где мы использовали основную функцию
selected()
и вспомогательную функцию:Затем мы могли бы также использовать это при проверке выбранного раздела курса в
pre_get_users
обратном вызове действия.источник
static
ключевое слово таким образом (только в классах). Есть ли$instance
стать глобальной переменной , когда вы это делаете? Вам нужно беспокоиться о конфликтах имен переменных? Мне также нравится техника создания нового действия, которое поддерживает уже существующее. Спасибо!Я проверил ваш код как в Wordpress 4.4, так и в Wordpress 4.3.1. С версией 4.4 я сталкиваюсь точно с той же проблемой, что и вы. Тем не менее, ваш код работает правильно в версии 4.3.1!
Я думаю, что это ошибка Wordpress. Я не знаю, сообщалось ли об этом еще. Я думаю, что причина ошибки может заключаться в том, что кнопка отправки отправляет запрос дважды. Если вы посмотрите на переменные запроса, то увидите, что поле course_section указано дважды, один раз с правильным значением и один раз пустым.
Редактировать: это решение JavaScript
Просто добавьте это в файл functions.php вашей темы и измените NAME_OF_YOUR_INPUT_FIELD на имя вашего поля ввода! Поскольку WordPress автоматически загружает jQuery на стороне администратора, вам не нужно ставить в очередь какие-либо сценарии. Этот фрагмент кода просто добавляет прослушиватель изменений к раскрывающимся входам, а затем автоматически обновляет другой раскрывающийся список в соответствии с тем же значением. Больше объяснений здесь.
Надеюсь это поможет!
источник
Filter
она отправляет правильное значение, но затем снова перенаправляет обратно на страницу, на этот раз удаляя значение. Я предполагаю, что это своего рода «функция» безопасности, предотвращающая отправку случайных, потенциально вредоносных значений, но я не знаю, как обойти это. Вздох.name
атрибут. Если я использую раскрывающийся список НИЖЕ таблицы, чтобы выполнить фильтрацию, она работает как положено. Поскольку это поле находится после того, что находится над ним, его нулевое значение переопределяет предыдущее. Хммм ....Это другое решение Javascript, которое может быть полезно для некоторых людей. В моем случае я просто полностью удалил второй (нижний) список выбора. Я считаю, что я никогда не использую нижние входы в любом случае ...
источник
Решение не на JavaScript
Присвойте select имя в стиле «массив», например:
Затем передаются ОБА параметры (сверху и снизу таблицы), и теперь в известном формате массива.
Затем значение можно использовать следующим образом в
pre_get_users
функции:источник
другое решение
Вы можете поместить свой фильтр выбора в отдельный файл, как
user_list_filter.php
и использовать
require_once 'user_list_filter.php'
в вашем действии функцию обратного вызоваuser_list_filter.php
файл:и в вашем действии обратный вызов:
источник