¿Cómo crear opciones de filtro personalizadas en wp_list_table?
Usé la clase wp_list_table
para crear mi tabla personalizada en el backend. Está funcionando bien.
Ahora, quiero agregar filtros como en la imagen de abajo.
Aquí está mi código existente para renderizar la tabla de administración con mi información personalizada.
if( ! class_exists( 'WP_List_Table' ) ) {
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
class Kv_subscribers_list extends WP_List_Table {
function __construct(){
global $status, $page;
parent::__construct( array(
'singular' => 'notificación', // Nombre singular
'plural' => 'notificaciones', // Nombre plural
'ajax' => false
) );
}
function column_default($item, $column_name){
switch($column_name){
case 'email':
case 'date':
case 'common':
case 'unit_id':
return $item[$column_name];
default:
return print_r($item,true); // Muestra todo el array para propósitos de depuración
}
}
function column_email($item){
$actions = array(
'email' => sprintf('<a href="?page=%s&action=%s&email_id=%s">Correo</a>',$_REQUEST['page'],'email',$item['id']),
'delete' => sprintf('<a href="?page=%s&action=%s&delete_id=%s">Eliminar</a>',$_REQUEST['page'],'delete',$item['id']),
);
// Devuelve el contenido del título
return sprintf('%1$s %2$s',
/*$1%s*/ $item['email'],
/*$2%s*/ $this->row_actions($actions)
);
}
function column_cb($item){
return sprintf(
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
/*$1%s*/ $this->_args['singular'],
/*$2%s*/ $item['id']
);
}
function get_columns(){
$columns = array(
'cb' => '<input type="checkbox" />', // Renderiza un checkbox en lugar de texto
'email'=>__('Fecha'),
'date'=>__('Fecha'),
'common'=>__('Alerta Común'),
'unit_id'=>__('ID Único')
);
return $columns;
}
public function get_sortable_columns() {
$sortable_columns = array(
'email' => array('wp_user_id',false), // true significa que ya está ordenado
'date' => array('date',false),
'common' => array('common',false)
);
return $sortable_columns;
}
public function get_bulk_actions() {
$actions = array(
'delete' => 'Eliminar',
'email' => 'Correo'
);
return $actions;
}
public function process_bulk_action() {
global $wpdb;
$notifications_tbl = $wpdb->prefix.'newsletter';
if( 'delete'===$this->current_action() ) {
foreach($_POST['notification'] as $single_val){
$wpdb->delete( $notifications_tbl, array( 'id' => (int)$single_val ) );
}
$redirect_url = get_admin_url( null, 'admin.php?page=subscribers' );
wp_safe_redirect($redirect_url);
wp_die('¡Elementos eliminados (o lo serían si tuviéramos elementos para eliminar)!');
}
if( 'email'===$this->current_action() ) {
$result_email_ar = implode("-",$_POST['notification']);
$redirect_url = get_admin_url( null, 'admin.php?page=kvcodes&ids='.$result_email_ar );
wp_safe_redirect($redirect_url);
wp_die(' ');
}
}
function prepare_items() {
global $wpdb; // Esto se usa solo si se realizan consultas a la base de datos
$database_name = $wpdb->prefix.'newsletter' ;
$per_page = 10;
$query = "SELECT * FROM $database_name ORDER BY id DESC";
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array($columns, $hidden, $sortable);
$this->process_bulk_action();
$data = $wpdb->get_results($query, ARRAY_A );
function usort_reorder($a,$b){
$orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'title'; // Si no hay orden, por defecto título
$order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc'; // Si no hay orden, por defecto ascendente
$result = strcmp($a[$orderby], $b[$orderby]); // Determina el orden
return ($order==='asc') ? $result : -$result; // Envía la dirección de ordenamiento final a usort
}
// usort($data, 'usort_reorder');
$current_page = $this->get_pagenum();
$total_items = count($data);
$data = array_slice($data,(($current_page-1)*$per_page),$per_page);
$this->items = $data;
$this->set_pagination_args( array(
'total_items' => $total_items, // Tenemos que calcular el número total de elementos
'per_page' => $per_page, // Tenemos que determinar cuántos elementos mostrar por página
'total_pages' => ceil($total_items/$per_page) // Tenemos que calcular el número total de páginas
) );
}
}//class
y
echo '<form method="post">';
$mydownloads = new Kv_subscribers_list();
echo '</pre><div class="wrap"><h2>Suscriptores<a href="'."http://".$_SERVER["SERVER_NAME"].$_SERVER['REQUEST_URI'].'&add_new=true" class="add-new-h2">Añadir Nuevo</a></h2>';
$mydownloads->prepare_items();
$mydownloads->display();
echo '</div></form>';
Ahora, quiero hacer los filtros como
Todos || Publicados || Papelera
Necesito crear un filtro personalizado como este.

Código
class Kv_subscribers_list extends WP_List_Table {
function __construct(){
global $status, $page;
parent::__construct( array(
'singular' => 'notification',
'plural' => 'notifications',
'ajax' => false
) );
}
protected function get_views() {
$status_links = array(
"all" => __("<a href='#'>All</a>",'my-plugin-slug'),
"published" => __("<a href='#'>Published</a>",'my-plugin-slug'),
"trashed" => __("<a href='#'>Trashed</a>",'my-plugin-slug')
);
return $status_links;
}
function column_default($item, $column_name){
switch($column_name){
case 'email':
case 'date':
case 'common':
case 'unit_id':
return $item[$column_name];
default:
return print_r($item,true);
}
}
function column_email($item){
$actions = array(
'email' => sprintf('<a href="?page=%s&action=%s&email_id=%s">E-mail</a>',$_REQUEST['page'],'email',$item['id']),
'delete' => sprintf('<a href="?page=%s&action=%s&delete_id=%s">Delete</a>',$_REQUEST['page'],'delete',$item['id']),
);
return sprintf('%1$s %2$s',
/*$1%s*/ $item['email'],
/*$2%s*/ $this->row_actions($actions)
);
}
function column_cb($item){
return sprintf(
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
/*$1%s*/ $this->_args['singular'],
/*$2%s*/ $item['id']
);
}
function get_columns(){
$columns = array(
'cb' => '<input type="checkbox" />',
'email'=>__('Email'),
'date'=>__('Date'),
'common'=>__('Common Alert'),
'unit_id'=>__('Unique ID')
);
return $columns;
}
public function get_sortable_columns() {
$sortable_columns = array(
'email' => array('wp_user_id',false),
'date' => array('date',false),
'common' => array('common',false)
);
return $sortable_columns;
}
public function get_bulk_actions() {
$actions = array(
'delete' => 'Delete',
'email' => 'Email'
);
return $actions;
}
public function process_bulk_action() {
global $wpdb;
$notifications_tbl = $wpdb->prefix.'newsletter';
if( 'delete'===$this->current_action() ) {
foreach($_POST['notification'] as $single_val){
$wpdb->delete( $notifications_tbl, array( 'id' => (int)$single_val ) );
}
$redirect_url = get_admin_url( null, 'admin.php?page=subscribers' );
wp_safe_redirect($redirect_url);
wp_die('Items deleted (or they would be if we had items to delete)!');
}
if( 'email'===$this->current_action() ) {
$result_email_ar = implode("-",$_POST['notification']);
$redirect_url = get_admin_url( null, 'admin.php?page=kvcodes&ids='.$result_email_ar );
wp_safe_redirect($redirect_url);
wp_die(' ');
}
}
function prepare_items() {
global $wpdb;
$database_name = $wpdb->prefix.'newsletter';
$per_page = 10;
$query = "SELECT * FROM $database_name ORDER BY id DESC";
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array($columns, $hidden, $sortable);
$this->process_bulk_action();
$data = $wpdb->get_results($query, ARRAY_A);
function usort_reorder($a,$b){
$orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'title';
$order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc';
$result = strcmp($a[$orderby], $b[$orderby]);
return ($order==='asc') ? $result : -$result;
}
$current_page = $this->get_pagenum();
$total_items = count($data);
$data = array_slice($data,(($current_page-1)*$per_page),$per_page);
$this->items = $data;
$this->set_pagination_args( array(
'total_items' => $total_items,
'per_page' => $per_page,
'total_pages' => ceil($total_items/$per_page)
) );
}
}//class
Página de Administración & Ejemplo de Renderizado
function o_add_menu_items(){
add_menu_page('Plugin List Table', 'Sub', 'activate_plugins', 'subscribers', 'o_render_list_page');
}
add_action('admin_menu', 'o_add_menu_items');
function o_render_list_page() {
$mydownloads = new Kv_subscribers_list();
$title = __("Subscribers","my_plugin_slug");
?>
<div class="wrap">
<h1>
<?php echo esc_html( $title );?>
<a href="<?php echo admin_url( 'admin.php?page=subscribers&add_new=true' ); ?>" class="page-title-action">
<?php echo esc_html_x('Add New', 'my-plugin-slug'); ?>
</a>
<?php
?>
</h1>
</div>
<?php $mydownloads->views(); ?>
<form method="post">
<?php
$mydownloads->prepare_items();
$mydownloads->display();
?>
</form>
<?php
}
Explicación
We need to override WP_List_Table
class method get_views to get status links on the top.By default it is an empty array.
views method of WP_List_Table
uses get_views to display list of those links that we return in the get_views as an associative array with separator |
.
We can also override views method to have more control , for example if we want to change separator.
Take a look at how other list tables are using that. For instance check WP_Posts_List_Table.
After you have overridden the method then place $mydownloads->views();
.be sure to escape all and internationalize strings.
Using Filter
We can use views_{$this->screen->id}
filter once we have added get_views method.
Assuming toplevel_page_subscribers
as screen id
add_filter('views_toplevel_page_subscribers','my_plugin_slug_status_links',10, 1);
function my_plugin_slug_status_links($views) {
$views['scheduled'] = "<a href='#'>Scheduled</a>";
return $views;
}

Bueno, sé que esto llega bastante tarde, pero como este es el primer resultado en Google al buscar sobre filtrado en WP_List_Table, debo decirles que existe la función extra_tablenav
disponible para sobrescribir en tu extensión de clase:
class Kv_subscribers_list extends WP_List_Table {
function extra_tablenav( $which )
{
switch ( $which )
{
case 'top':
// Tu código HTML para mostrar
break;
case 'bottom':
// Tu código HTML para mostrar
break;
}
}
}
Si deseas mostrar contenido en ambas secciones, simplemente ignora el switch y coloca tu código HTML directamente al inicio de la función.

Puedes usar
<?php
class Kv_subscribers_list extends WP_List_Table {
function extra_tablenav( $which )
{
switch ( $which )
{
case 'top':
// Tu código HTML para mostrar
global $wpdb, $wp_locale;
$extra_checks = "AND status != 'auto-draft'";
if ( ! isset( $_GET['status'] ) || 'trash' !== $_GET['status'] ) {
$extra_checks .= " AND status != 'trash'";
} elseif ( isset( $_GET['status'] ) ) {
$extra_checks = $wpdb->prepare( ' AND status = %s', $_GET['status'] );
}
$sql = "
SELECT DISTINCT YEAR( create_date ) AS year, MONTH( create_date ) AS month
FROM ".$wpdb->prefix."audio_record
WHERE 1 = 1
$extra_checks
ORDER BY create_date DESC";
$months = $wpdb->get_results(
$wpdb->prepare(
$sql
)
);
$month_count = count( $months );
if ( ! $month_count || ( 1 == $month_count && 0 == $months[0]->month ) ) {
return;
}
$m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0;
$wp_query = add_query_arg();
$wp_query = remove_query_arg('m');
$link = esc_url_raw($wp_query);
?>
<div class="alignleft actions">
<select name="m" id="filter-by-date">
<option<?php selected( $m, 0 ); ?> value="0" data-rc="<?php _e($link); ?>"><?php _e( 'Todas las fechas' ); ?></option>
<?php
foreach ( $months as $arc_row ) {
if ( 0 == $arc_row->year ) {
continue;
}
$month = zeroise( $arc_row->month, 2 );
$year = $arc_row->year;
$wp_query = add_query_arg('m', $arc_row->year . $month);
$link = esc_url_raw($wp_query);
printf(
"<option %s value='%s' data-rc='%s'>%s</option>\n",
selected( $m, $year . $month, false ),
esc_attr( $arc_row->year . $month ),
esc_attr( $link),
/* translators: 1: Nombre del mes, 2: Año de 4 dígitos. */
sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month ), $year )
);
}
?>
</select>
<a href="javascript:void(0)" class="button" onclick="window.location.href = jQuery('#filter-by-date option:selected').data('rc');">Filtrar</a>
</div>
<?php
break;
break;
case 'bottom':
// Tu código HTML para mostrar
break;
}
}
}
y para la acción de consulta, puedes agregar código en
public function prepare_items()
o función get_customers
$this->items = self::get_customers($per_page, $current_page);
<?php
//public static function get_customers($per_page = 20, $page_number = 1)
if (!empty($_REQUEST['m'])) {
$search = $_REQUEST['m'];
$year = substr($search,0,4);
$month = substr($search,4,5);
if(!empty($year)){
$sql .= ' And YEAR(create_date)="' . $year . '"';
}
if(!empty($month)){
$sql .= ' And MONTH(create_date)="' . $month . '"';
}
}
Este es un ejemplo para obtener de mi base de datos
Cuando haces clic en el botón Filtrar irá a la URL desde data-rc
