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
$whichzmiennej, 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_usersakcja jest wywoływana dwukrotnie: raz POWYŻEJ tabeli użytkowników i raz PONIŻEJ. Oznacza to, że selecttworzone są DWIE listy rozwijane o tej samej nazwie . Po Filterkliknięciu przycisku dowolna wartość znajdująca się w drugim selectelemencie (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_usersakcja 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 $whichzmienną, która mówi jej, czy tworzy selectpowyższą czy pod formularzem, i pozwala nadać obu listom różne nameatrybuty. Niestety$which zmienna nie jest przekazywana do restrict_manage_usersakcji, 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ę!