UPDATE 2018-06-28
Sementara kode di bawah sebagian besar berfungsi dengan baik, berikut adalah penulisan ulang kode untuk WP> = 4.6.0 (menggunakan 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');
Saya memasukkan beberapa ide dari @birgire dan @cale_b yang juga menawarkan solusi di bawah ini yang layak dibaca. Secara khusus, saya:
- Menggunakan
$which
variabel yang ditambahkan div4.6.0
- Digunakan praktik terbaik untuk i18n dengan menggunakan string yang dapat diterjemahkan, misalnya
__( 'Filter' )
- Ditukar loop untuk (lebih modis?)
array_map()
, array_filter()
Danrange()
- Digunakan
sprintf()
untuk membuat templat markup
- Digunakan notasi array braket persegi bukan
array()
Terakhir, saya menemukan bug dalam solusi saya sebelumnya. Solusi-solusi itu selalu mendukung TOP <select>
daripada BOTTOM <select>
. Jadi jika Anda memilih opsi filter dari dropdown atas, dan kemudian memilih satu dari dropdown bawah, filter masih akan hanya menggunakan nilai apa pun yang ada di atas (jika tidak kosong). Versi baru ini memperbaiki bug itu.
PEMBARUAN 2018-02-14
Ini masalah telah ditambal sejak WP 4.6.0 dan perubahan didokumentasikan dalam dokumen resmi . Namun, solusi di bawah masih berfungsi.
Apa yang Menyebabkan Masalah (WP <4.6.0)
Masalahnya adalah bahwa restrict_manage_users
tindakan dipanggil dua kali: sekali DI ATAS tabel Pengguna, dan sekali DI BAWAH. Ini berarti bahwa DUA select
dropdown dibuat dengan nama yang sama . Ketika Filter
tombol diklik, nilai apa pun yang ada di select
elemen kedua (yaitu yang DI BAWAH tabel) menimpa nilai di yang pertama, yaitu yang di atas tabel.
Jika Anda ingin masuk ke sumber WP, restrict_manage_users
tindakan dipicu dari dalam WP_Users_List_Table::extra_tablenav($which)
, yang merupakan fungsi yang menciptakan dropdown asli untuk mengubah peran pengguna. Fungsi itu memiliki bantuan dari $which
variabel yang memberitahukannya apakah itu membuat select
formulir di atas atau di bawah, dan memungkinkannya untuk memberikan dua dropdown name
atribut yang berbeda . Sayangnya, $which
variabel tidak diteruskan ke restrict_manage_users
tindakan, jadi kami harus menemukan cara lain untuk membedakan elemen khusus kami.
Salah satu cara untuk melakukan ini, seperti yang disarankan oleh @Linnea , adalah menambahkan beberapa JavaScript untuk menangkap Filter
klik dan menyinkronkan nilai-nilai dari kedua dropdown. Saya memilih solusi khusus PHP yang akan saya jelaskan sekarang.
Bagaimana memperbaikinya
Anda dapat memanfaatkan kemampuan untuk mengubah input HTML menjadi array nilai, dan kemudian menyaring array untuk menghilangkan nilai yang tidak ditentukan. Berikut kodenya:
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' );
Bonus: PHP 7 Refactor
Karena saya senang dengan PHP 7, jika Anda menjalankan WP pada server PHP 7, inilah versi yang lebih pendek dan seksi menggunakan operator penggabungan nol??
:
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' );
Nikmati!