ОНОВЛЕННЯ 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 Refactor
Оскільки я в захваті від PHP 7, якщо ви працюєте з WP на сервері PHP 7, ось коротша, сексуальна версія, використовуючи оператор null coalescing??
:
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' );
Насолоджуйтесь!