AKTUALIZACJA 28.06.2018
Chociaż poniższy kod w większości działa dobrze, oto przepisanie kodu dla WP> = 4.6.0 (przy użyciu 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');
Włączyłem kilka pomysłów od @birgire i @cale_b, które oferują również rozwiązania, które warto przeczytać. W szczególności:
- Użyto
$which
zmiennej, która została dodanav4.6.0
- Zastosowano najlepszą praktykę dla i18n, stosując przekładalne ciągi znaków, np
__( 'Filter' )
- Wymieniane pętle dla (bardziej modne?)
array_map()
, array_filter()
Orazrange()
- Służy
sprintf()
do generowania szablonów znaczników
- Zamiast notacji zastosowano tablicę nawiasów kwadratowych
array()
Wreszcie odkryłem błąd w moich wcześniejszych rozwiązaniach. Te rozwiązania zawsze faworyzują TOP <select>
nad DOLNYM <select>
. Jeśli więc wybierzesz opcję filtrowania z górnego menu rozwijanego, a następnie wybierz jeden z dolnego menu rozwijanego, filtr będzie nadal używał tylko tej wartości, która była na górze (jeśli nie jest pusta). Ta nowa wersja naprawia ten błąd.
AKTUALIZACJA 14.02.2018
Ten problem został załatany od wersji WP 4.6.0, a zmiany są udokumentowane w oficjalnych dokumentach . Poniższe rozwiązanie nadal jednak działa.
Co było przyczyną problemu (WP <4.6.0)
Problem polegał na tym, że restrict_manage_users
akcja jest wywoływana dwukrotnie: raz POWYŻEJ tabeli użytkowników i raz PONIŻEJ. Oznacza to, że select
tworzone są DWIE listy rozwijane o tej samej nazwie . Po Filter
kliknięciu przycisku dowolna wartość znajdująca się w drugim select
elemencie (tj. PONIŻEJ tabeli) zastępuje wartość w pierwszym elemencie, tj. Powyżej tabeli.
Jeśli chcesz zanurzyć się w źródle WP, restrict_manage_users
akcja jest uruchamiana od wewnątrz WP_Users_List_Table::extra_tablenav($which)
, czyli funkcji, która tworzy natywne menu rozwijane, aby zmienić rolę użytkownika. Ta funkcja ma $which
zmienną, która mówi jej, czy tworzy select
powyższą czy pod formularzem, i pozwala nadać obu listom różne name
atrybuty. Niestety$which
zmienna nie jest przekazywana do restrict_manage_users
akcji, dlatego musimy wymyślić inny sposób na odróżnienie własnych elementów niestandardowych.
Jednym ze sposobów na zrobienie tego, jak sugeruje @Linnea , byłoby dodanie JavaScript, aby go złapaćFilter
kliknięcie i zsynchronizować wartości dwóch list rozwijanych. Wybrałem rozwiązanie oparte tylko na PHP, które opiszę teraz.
Jak to naprawić
Możesz skorzystać z możliwości przekształcania danych HTML w tablice wartości, a następnie filtrować tablicę, aby pozbyć się wszelkich niezdefiniowanych wartości. Oto kod:
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' );
Premia: Refaktor PHP 7
Ponieważ jestem podekscytowany PHP 7, na wypadek, gdybyś uruchomił WP na serwerze PHP 7, oto krótsza, bardziej seksowna wersja z operatorem koalescencji 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' );
Cieszyć się!