อัพเดท 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
นี้ปัญหาได้รับการ patched ตั้งแต่ 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 ต่อไปนี้เป็นเวอร์ชันที่สั้นกว่าและเซ็กซี่กว่าโดยใช้ตัวดำเนินการรวม??
ศูนย์เป็นโมฆะ :
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' );
สนุก!