Filtrar por campo personalizado en tipo de entrada personalizada en página de administración

21 dic 2015, 15:31:56
Vistas: 37K
Votos: 13

He usado Advanced Custom Fields para crear campos personalizados para nombre de Competición, respuestas, etc. He creado un tipo de entrada personalizada para competiciones como se muestra en la imagen y utilicé functions.php de WordPress para crear las columnas con los valores de mis campos personalizados.

Estoy tratando de obtener un cuadro desplegable "Filtrar por" con los diferentes nombres/etiquetas de las competiciones como se muestra abajo, pero solo encuentro soluciones usando taxonomías, las cuales prefiero no usar si es posible porque he usado campos personalizados para todo lo demás.

¿Es posible crear un desplegable "Filtrar por" personalizado usando solo campos personalizados?

Filtro de WordPress

2
Comentarios

Puedes hacer uso del hook de acción restrict_manage_posts para agregar cuadros desplegables adicionales. No olvides que también tendrías que agregar algo de lógica para el filtro, ya que WP no sabrá qué hacer con él directamente (a diferencia de las listas desplegables de taxonomías, que puede manejar automáticamente).

David Gard David Gard
21 dic 2015 15:41:38

Como pensamiento adicional - si lo deseas, puedes convertir el Nombre en un enlace dentro de tu List Table, lo que significa que puedes filtrar una Competencia haciendo clic en el nombre, en lugar de tener un desplegable.

David Gard David Gard
21 dic 2015 17:10:11
Todas las respuestas a la pregunta 5
2
14

Y para mostrar el resultado del Filtro, prueba este código

add_filter( 'parse_query', 'prefix_parse_filter' );
function prefix_parse_filter($query) {
   global $pagenow;
   $current_page = isset( $_GET['post_type'] ) ? $_GET['post_type'] : '';
   
   if ( is_admin() && 
     'competition' == $current_page &&
     'edit.php' == $pagenow && 
      isset( $_GET['competition-name'] ) && 
      $_GET['competition-name'] != '' ) {
   
    $competition_name                  = $_GET['competition-name'];
    $query->query_vars['meta_key']     = 'competition_name';
    $query->query_vars['meta_value']   = $competition_name;
    $query->query_vars['meta_compare'] = '=';
  }
}

Cambia la meta clave y el meta valor según sea necesario. He tomado "competition_name" como meta_key y "competition-name" como nombre del menú desplegable.

21 dic 2015 16:32:28
Comentarios

Genial, me sentía perezoso así que le sugerí que hiciera una pregunta adicional ;)

David Gard David Gard
21 dic 2015 17:11:00

Parece que las 2 respuestas forman una respuesta completa y deberían combinarse.

RCNeil RCNeil
10 jul 2017 20:28:07
2
11

La acción restrict_manage_posts activa la función add_extra_tablenav(), que es como agregas menús desplegables adicionales a tu List Table deseada.

En el ejemplo a continuación, primero nos aseguramos de que el Tipo de Entrada sea el correcto, y luego obtenemos todos los valores de la base de datos almacenados con la clave competition_name en la tabla postmeta (debes cambiar el nombre de la clave según sea necesario). La consulta es bastante básica y solo verifica si la Competencia está publicada, toma solo valores únicos (no quieres duplicados en el menú desplegable) y luego los ordena alfabéticamente.

Luego verificamos si hay resultados (no tiene sentido mostrar el menú desplegable si no hay nada), y construimos las opciones (incluyendo una opción predeterminada para mostrar todo). Finalmente, mostramos el menú desplegable.

Como mencioné en mi comentario, esto no es todo; necesitarás algo de lógica para decirle al List Table que solo muestre los resultados deseados cuando el filtro esté activo, pero te dejaré investigar eso y luego puedes hacer otra pregunta si necesitas más ayuda. Pista - revisa el archivo /wp-admin/includes/class-wp-posts-list-table.php, y su padre .../wp-class-list-table.php

/**
 * Agrega menús desplegables adicionales a las List Tables
 *
 * @param required string $post_type    El Tipo de Entrada que se está mostrando
 */
add_action('restrict_manage_posts', 'add_extra_tablenav');
function add_extra_tablenav($post_type){
    
    global $wpdb;
    
    /** Asegurar que este es el Tipo de Entrada correcto */
    if($post_type !== 'competition')
        return;
    
    /** Obtener los resultados de la base de datos */
    $query = $wpdb->prepare('
        SELECT DISTINCT pm.meta_valor FROM %1$s pm
        LEFT JOIN %2$s p ON p.ID = pm.post_id
        WHERE pm.meta_clave = "%3$s" 
        AND p.post_status = "%4$s" 
        AND p.post_type = "%5$s"
        ORDER BY "%6$s"',
        $wpdb->postmeta,
        $wpdb->posts,
        'competition_name', // Tu meta clave - cambia según sea necesario
        'publish',          // Estado de la entrada - cambia según sea necesario
        $post_type,
        'competition_name'
    );
    $resultados = $wpdb->get_col($query);
    
    /** Asegurarse de que hay opciones para mostrar */
    if(empty($resultados))
        return;

    // obtener la opción seleccionada si hay una seleccionada
    if (isset( $_GET['competition-name'] ) && $_GET['competition-name'] != '') {
        $nombreSeleccionado = $_GET['competition-name'];
    } else {
        $nombreSeleccionado = -1;
    }
    
    /** Obtener todas las opciones que deberían mostrarse */
    $opciones[] = sprintf('<option value="-1">%1$s</option>', __('Todas las Competencias', 'tu-dominio-de-texto'));
    foreach($resultados as $resultado) :
        if ($resultado == $nombreSeleccionado) {
            $opciones[] = sprintf('<option value="%1$s" selected>%2$s</option>', esc_attr($resultado), $resultado);
        } else {
            $opciones[] = sprintf('<option value="%1$s">%2$s</option>', esc_attr($resultado), $resultado);
        }
    endforeach;

    /** Mostrar el menú desplegable */
    echo '<select class="" id="competition-name" name="competition-name">';
    echo join("\n", $opciones);
    echo '</select>';

}
21 dic 2015 16:18:17
Comentarios

Al usar esto, obtengo el error Notice: wpdb::prepare fue llamado incorrectamente. La consulta no contiene el número correcto de marcadores de posición (6) para la cantidad de argumentos pasados (5). Por favor, consulta Depuración en WordPress para más información. (Este mensaje fue agregado en la versión 4.8.3.) en /[...]/wp-includes/functions.php en la línea 4773

rassoh rassoh
10 jul 2019 14:28:10

También estoy obteniendo el mismo error

Vasim Shaikh Vasim Shaikh
30 ene 2020 21:02:37
0

Si esto no funciona para alguien, mi solución fue necesitar agregar la columna que estaba intentando filtrar a la lista de columnas ordenables para mi tipo de publicación personalizada.

// Hacer que las columnas personalizadas del Tipo de Publicación Personalizada sean ordenables
function cpt_custom_columns_sortable( $columns ) {

    // Añadir nuestras columnas al array $columns
    $columns['item_number'] = 'item_number';
    $columns['coat_school'] = 'coat_school'; 

    return $columns;
} add_filter( 'manage_edit-your-custom-post-type-slug_sortable_columns', 'cpt_custom_columns_sortable' );
9 abr 2019 18:46:04
0

Reemplaza la consulta a continuación para corregir el error wpdb:prepare:

$query = $wpdb->prepare('
        SELECT DISTINCT pm.meta_value FROM %1$s pm
        LEFT JOIN %2$s p ON p.ID = pm.post_id
        WHERE pm.meta_key = "%3$s" 
        AND p.post_status = "%4$s" 
        AND p.post_type = "%5$s"
        ORDER BY "%3$s"',
        $wpdb->postmeta,
        $wpdb->posts,
        'competition_name', // Tu clave meta - cambia según sea necesario
        'publish',          // Estado del post - cambia según sea necesario
        $post_type,
        'competition_name' //esto se necesita una segunda vez para definir "%3$s" en ORDER BY
  );
12 mar 2020 16:44:25
0

Me encontré con el mismo problema al intentar filtrar un tipo de entrada personalizado (custom-post-type) con un campo personalizado (custom-field)
pero resolví este problema siguiendo estos pasos.
Convertí el nombre del campo personalizado de writer a _writer
y luego actualicé el siguiente código dentro de la función de callback del hook parse_query para poder agregar la meta_query del campo personalizado así:

$query->set( 'meta_query', array(
    array(
          'key'     => '_writer',
           'compare' => '=',
           'value'   => $_GET['_writer'],
           'type'    => 'numeric',
      )
) );         

Esta solución anterior funcionó para mí.
Documentación https://developer.wordpress.org/reference/hooks/pre_get_posts/
Enlaces útiles https://developer.wordpress.org/reference/hooks/pre_get_posts/#comment-2571
https://stackoverflow.com/questions/47869905/how-can-i-filter-records-in-custom-post-type-list-in-admin-based-on-user-id-that

8 jul 2020 01:19:25