El problema
WP parece eliminar el valor de mi variable de consulta antes de que se use para filtrar la lista de usuarios.
Mi código
Esta función agrega una columna personalizada a mi tabla Usuarios en /wp-admin/users.php
:
function add_course_section_to_user_meta( $columns ) {
$columns['course_section'] = 'Section';
return $columns;
}
add_filter( 'manage_users_columns', 'add_course_section_to_user_meta' );
Esta función le dice a WP cómo llenar valores en la columna:
function manage_users_course_section( $val, $col, $uid ) {
if ( 'course_section' === $col )
return get_the_author_meta( 'course_section', $uid );
}
add_filter( 'manage_users_custom_column', 'manage_users_course_section' );
Esto agrega un menú desplegable y un Filter
botón sobre la tabla Usuarios:
function add_course_section_filter() {
echo '<select name="course_section" style="float:none;">';
echo '<option value="">Course Section...</option>';
for ( $i = 1; $i <= 3; ++$i ) {
if ( $i == $_GET[ 'course_section' ] ) {
echo '<option value="'.$i.'" selected="selected">Section '.$i.'</option>';
} else {
echo '<option value="'.$i.'">Section '.$i.'</option>';
}
}
echo '<input id="post-query-submit" type="submit" class="button" value="Filter" name="">';
}
add_action( 'restrict_manage_users', 'add_course_section_filter' );
Esta función altera la consulta del usuario para agregar mi meta_query
:
function filter_users_by_course_section( $query ) {
global $pagenow;
if ( is_admin() &&
'users.php' == $pagenow &&
isset( $_GET[ 'course_section' ] ) &&
!empty( $_GET[ 'course_section' ] )
) {
$section = $_GET[ 'course_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' );
Otra información
Crea mi menú desplegable correctamente. Cuando selecciono una sección del curso y hago clic en Filter
la página se actualiza y course_section
aparece en la URL, pero no tiene ningún valor asociado. Si reviso las solicitudes HTTP, muestra que se envía con el valor de la variable correcta, pero luego hay una 302 Redirect
que parece eliminar el valor que seleccioné.
Si envío la course_section
variable escribiéndola directamente en la URL, el filtro funciona como se esperaba.
Mi código se basa aproximadamente en este código de Dave Court .
También intenté incluir en la lista blanca mi consulta var usando este código, pero sin suerte:
function add_course_section_query_var( $qvars ) {
$qvars[] = 'course_section';
return $qvars;
}
add_filter( 'query_vars', 'add_course_section_query_var' );
Estoy usando WP 4.4. ¿Alguna idea de por qué mi filtro no funciona?
Respuestas:
ACTUALIZACIÓN 2018-06-28
Si bien el siguiente código funciona bien, aquí hay una reescritura del código para WP> = 4.6.0 (usando PHP 7):
Incorporé varias ideas de @birgire y @cale_b que también ofrecen soluciones a continuación que vale la pena leer. Específicamente, yo:
$which
variable que se agregó env4.6.0
__( 'Filter' )
array_map()
,array_filter()
Yrange()
sprintf()
para generar las plantillas de marcadoarray()
Por último, descubrí un error en mis soluciones anteriores. Esas soluciones siempre favorecen lo SUPERIOR
<select>
sobre lo INFERIOR<select>
. Entonces, si seleccionó una opción de filtro en el menú desplegable superior y luego selecciona una del menú desplegable inferior, el filtro solo usará el valor que esté arriba (si no está en blanco). Esta nueva versión corrige ese error.ACTUALIZACIÓN 2018-02-14
Este problema ha sido parcheado desde WP 4.6.0 y los cambios están documentados en los documentos oficiales . Sin embargo, la solución a continuación todavía funciona.
Qué causó el problema (WP <4.6.0)
El problema era que la
restrict_manage_users
acción se llamaba dos veces: una vez POR ENCIMA de la tabla Usuarios, y una vez POR DEBAJO. Esto significa queselect
se crean DOS menús desplegables con el mismo nombre . CuandoFilter
se hace clic en el botón, cualquier valor que esté en el segundoselect
elemento (es decir, el DEBAJO de la tabla) anula el valor en el primero, es decir, el que está SOBRE LA tabla.En caso de que desee sumergirse en la fuente WP, la
restrict_manage_users
acción se activa desde dentroWP_Users_List_Table::extra_tablenav($which)
, que es la función que crea el menú desplegable nativo para cambiar la función de un usuario. Esa función tiene la ayuda de la$which
variable que le dice si está creandoselect
el formulario anterior o inferior, y le permite otorgar a los dos menús desplegablesname
atributos diferentes . Desafortunadamente, la$which
variable no se pasa a larestrict_manage_users
acción, por lo que tenemos que encontrar otra forma de diferenciar nuestros propios elementos personalizados.Una forma de hacerlo, como sugiere @Linnea , sería agregar algo de JavaScript para captar el
Filter
clic y sincronizar los valores de los dos menús desplegables. Elegí una solución solo para PHP que describiré ahora.Como arreglarlo
Puede aprovechar la capacidad de convertir las entradas HTML en matrices de valores y luego filtrar la matriz para deshacerse de los valores indefinidos. Aquí está el código:
Bonus: PHP 7 Refactor
Como estoy entusiasmado con PHP 7, en caso de que esté ejecutando WP en un servidor PHP 7, aquí hay una versión más corta y más sexy que utiliza el operador de fusión nula
??
:¡Disfrutar!
fuente
</select>
, también encontré que para que funcione, tuve que ponerlo<form method="get">
antes del menú de selección y</form>
después del botón de filtro.</select>
etiquetas que faltan ! Los agregué. Es extraño que necesitaras envolverlo<form>
ya que toda esta página está envuelta en una gran forma, y este código se inyecta en el medio. Aunque me alegra que lo hayas hecho funcionar. :)En el núcleo, los nombres de entrada inferiores están marcados con el número de instancia, por ejemplo
new_role
(arriba) ynew_role2
(abajo). Aquí hay dos enfoques para una convención de nomenclatura similar, a sabercourse_section1
(arriba) ycourse_section2
(abajo):Enfoque n. ° 1
Como la
$which
variable ( arriba , abajo ) no se pasa alrestrict_manage_users
gancho, podríamos evitarlo creando nuestra propia versión de ese gancho:Creemos el gancho de acción
wpse_restrict_manage_users
que tiene acceso a una$which
variable:Entonces podemos conectarlo con:
donde ahora tenemos
$name
quecourse_section1
en la parte superior ycourse_section2
en la parte inferior .Enfoque n. ° 2
Enganchemos
restrict_manage_users
, para mostrar menús desplegables, con un nombre diferente para cada instancia:donde usamos la función central
selected()
y la función auxiliar:Entonces también podríamos usar esto cuando verifiquemos la sección del curso seleccionado en la
pre_get_users
devolución de llamada de acción.fuente
static
palabra clave de esta manera (solo dentro de las clases). ¿Se$instance
convierte en una variable global cuando haces esto? ¿Tiene que preocuparse por las colisiones de nombres variables? También me gusta la técnica de crear una nueva acción que se apoya en una existente. ¡Gracias!Probé su código tanto en Wordpress 4.4 como en Wordpress 4.3.1. Con la versión 4.4, encuentro exactamente el mismo problema que tú. ¡Sin embargo, su código funciona correctamente en la versión 4.3.1!
Creo que este es un error de Wordpress. No sé si ya se ha informado. Creo que la razón detrás del error podría ser que el botón enviar envía dos veces la consulta. Si observa los vars de consulta, verá que course_section aparece dos veces, una con el valor correcto y otra vacía.
Editar: esta es la solución de JavaScript
¡Simplemente agregue esto al archivo functions.php de su tema y cambie NAME_OF_YOUR_INPUT_FIELD al nombre de su campo de entrada! Como WordPress carga automáticamente jQuery en el lado del administrador, no tiene que poner en cola ningún script. Este fragmento de código simplemente agrega un detector de cambios a las entradas desplegables y luego actualiza automáticamente el otro menú desplegable para que coincida con el mismo valor. Más explicaciones aquí.
¡Espero que esto ayude!
fuente
Filter
envía el valor correcto, pero luego vuelve a dirigir a la página, esta vez eliminando el valor. Supongo que es una especie de "característica" de seguridad para evitar el envío de valores aleatorios, potencialmente maliciosos, pero no sé cómo solucionarlo. Suspiro.name
atributo. Si uso el menú desplegable ABAJO de la tabla para hacer el filtrado, funciona como se esperaba. Dado que ese campo viene después del que está arriba, su valor nulo anula al anterior. Hmmm ....Esta es una solución Javascript diferente que puede ser útil para algunas personas. En mi caso, simplemente eliminé por completo la segunda lista de selección (inferior). Me parece que nunca uso las entradas inferiores de todos modos ...
fuente
Solución sin JavaScript
Dé a la selección un nombre que sea "estilo matriz", de esta manera:
Luego se pasan AMBOS parámetros (desde la parte superior y la parte inferior de la tabla), y ahora en un formato de matriz conocido.
Entonces, el valor se puede usar así en la
pre_get_users
función:fuente
otra solución
puedes poner tu cuadro de selección de filtro en un archivo separado como
user_list_filter.php
y usar
require_once 'user_list_filter.php'
en su función de devolución de llamada de acciónuser_list_filter.php
archivo:y en su devolución de llamada de acción:
fuente