La forma correcta de crear una página de búsqueda personalizada para tipos de publicaciones personalizadas complejas

4

Estoy intentando crear una página de búsqueda personalizada para mostrar solo tipos de publicaciones personalizadas que cumplan con criterios de búsqueda específicos. Tengo una forma compleja que involucra diferentes selecciones, botones de radio y campos de entrada de texto. Me siento cómodo utilizando la clase WP_Query para consultar las publicaciones que se identifican a través del formulario de búsqueda, pero no estoy seguro de si debo crear plantillas adicionales o usar la página de búsqueda integrada.

Déjame darte un ejemplo para ayudar a comunicar mi enigma. Imagina que tienes el CPT "Persona". Para cada persona, tiene "Fecha de nacimiento", "Género", "Altura" y "Peso". Desea buscar a todos los varones nacidos después de 1972, que son más altos que 6 pies de altura. ¿Cómo resolverías esta búsqueda? De nuevo, puedo juntar fácilmente $args para que la clase WP_Query obtenga estas publicaciones. Necesito saber la mejor manera de integrar esto con WordPress.

En última instancia, necesito una solución que satisfaga lo siguiente:

1) Conserva la paginación en la página de búsqueda 2) Solo busca el CPT específico, no otros CPT

Y, tengo las siguientes preguntas

1) ¿Debo tener una plantilla separada para esto, o puedo integrarla directamente con search.php ? Mi solución actual se siente mal y me gustaría desarrollar una alternativa. He creado una nueva página en el administrador de WP. Utilizo la URL de esta página como el atributo action en el formulario de búsqueda. Luego uso una plantilla personalizada para mostrar los resultados de esa página. Esto me parece mal.

2) Si integro esto con search.php , ¿cómo conservo los resultados de búsqueda regulares, además de tener estos encantadores resultados de búsqueda personalizados?

¡Muchas gracias por tu ayuda!

EDITAR: en una investigación adicional, estoy empezando a pensar que pre_get_posts probablemente estará involucrado de una "mejor manera" para hacer esto.

    
pregunta tollmanz 14.08.2011 - 21:19

1 respuesta

3

Encontré una manera de hacer que esto funcione. Estaba en lo cierto al pensar que pre_get_posts era el camino a seguir. Primero, agregué una acción:

// Filter the search page
add_filter('pre_get_posts', 'search_pre_get_posts');

Luego agregué la función. Esta función primero verifica que el contexto sea correcto. En mi formulario de búsqueda personalizado, uso un nonce. El nonce me ayuda a verificar que se está ejecutando mi búsqueda personalizada, no la búsqueda integrada. Luego manipulo las variables de consulta que serán enviadas a la consulta. Aquí muestro mi función completa, que incluye toda la validación y el saneamiento de las variables, así como la forma en que se manipula la consulta:

/**
 * Filters for search of events
 *
 * When a search is initiated, this filter will check to see if it is an
 * event search. If so, it will process the search data associated with
 * event searches and add it to the $query object prior to it being used
 * to query the database.
 *
 * @param $query The query object generated for this page
 * @return void
 */
function search_pre_get_posts($query)
{
    // Verify that we are on the search page that that this came from the event search form
    if($query->query_vars['s'] != '' && is_search() && isset($_GET['prefix-submitted']) && $_GET['prefix-submitted'] && wp_verify_nonce($_GET['prefix-search-nonce'], 'prefix-search'))
    {
        // Always order by date
        $query->set('orderby', 'meta_value');
        $query->set('order', 'ASC');
        $query->set('meta_key', '_datetime-from');

        // Set the text string for the search
        $clean_text = (isset($_GET['prefix-text'])) ? wp_strip_all_tags($_GET['prefix-text']) : '';
        $query->set('s', $clean_text);

        // Validate dates
        $clean_from = (isset($_GET['prefix-from'])) ? $this->handle_date($_GET['prefix-from']) : false;
        $clean_to = (isset($_GET['prefix-to'])) ? $this->handle_date($_GET['prefix-to']) : false;

        // Validate taxonomies
        $clean_type = (isset($_GET['prefix-type'])) ? $this->handle_taxonomy_id($_GET['prefix-type'], 'prefix-type') : false;
        $clean_location = (isset($_GET['prefix-location'])) ? $this->handle_taxonomy_id($_GET['prefix-location'], 'prefix-location') : false;

        // Build meta_query variable based on date pieces
        if($clean_from && $clean_to)
        {
            $meta_query = array(
                array(
                    'key' => '_datetime-from',
                    'value' => array($clean_from, $clean_to),
                    'compare' => 'BETWEEN',
                    'type' => 'DATE'
                )
            );
        }
        elseif($clean_from)
        {
            $meta_query = array(
                array(
                    'key' => '_datetime-from',
                    'value' => $clean_from,
                    'compare' => '>=',
                    'type' => 'DATE'
                )
            );
        }
        elseif($clean_to)
        {
            $meta_query = array(
                array(
                    'key' => '_datetime-from',
                    'value' => $clean_from,
                    'compare' => '>=',
                    'type' => 'DATE'
                )
            );
        }
        else
            $meta_query = '';

        // Set the meta query
        $query->set('meta_query', $meta_query);

        // Build tax query based on taxonomy pieces
        if($clean_type && $clean_location)
        {
            $tax_query = array(
                'relation' => 'AND',
                array(
                    'taxonomy' => 'prefix-type',
                    'field' => 'id',
                    'terms' => $clean_type,
                    'operator' => 'IN'
                ),
                array(
                    'taxonomy' => 'prefix-location',
                    'field' => 'id',
                    'terms' => $clean_location,
                    'operator' => 'IN'
                )
            );
        }
        elseif($clean_type)
        {
            $tax_query = array(
                array(
                    'taxonomy' => 'prefix-type',
                    'field' => 'id',
                    'terms' => $clean_type,
                    'operator' => 'IN'
                )
            );
        }
        elseif($clean_location)
        {
            $tax_query = array(
                array(
                    'taxonomy' => 'prefix-location',
                    'field' => 'id',
                    'terms' => $clean_location,
                    'operator' => 'IN'
                )
            );
        }
        else
            $tax_query = '';

        // Set the tax query
        $query->set('tax_query', $tax_query);
    }
}
    
respondido por el tollmanz 22.08.2011 - 06:53

Lea otras preguntas en las etiquetas