0

I'm a junior developer who is currently developing a Wordpress site that requires a hand-made, powerful search form.

I have a bunch of parent SIMPLE (normal, not custom) categories (Customers, Business Sectors, Operations and Business Areas), and then I've got some children categories (for example, the customer "TEST" is a subcategory of Customers, so you can understand me). Then, I categorize all of the posts according to the customer they belong, their business sector, area, etc. so every post has its categories.

In my search form, I've got the different subcategories PRELOADED in the header (no AJAX required), and attached to different SELECTS. Every select option has the "value" of the ID of the subcategory, so that's all good.

The thing is, the form can be sent totally EMPTY, searching only for specific words (classic Wordpress search), or picking some of the categories from the dropdown (which should be something like "in__category" for the WP_Query), or BOTH WORDS AND CATEGORIES.

Now, to the point: I've used WP_Query to search for Posts, first getting the parameters that are sent by the form, and then trying to add the arguments to the WP_Query, but I am not getting the expected results.

There is an specific case that is bothering me: I have a customer named "Starbucks", for example. If I search for "starbuck", I get about 5-6 posts that contain "Starbucks" in the title, but if I search for "Starbucks", I only get ONE POST using my current WP_Query.

Here is the code of my advanced-searchform.php

<?php
    //Función getSelectItems en functions.php, dado el SLUG de la categoria, obtiene las subcategorias hijas de la categoria del slug.
    $sectores = getSelectItems('sectores');
    $clientes = getSelectItems('clientes');
    $areas = getSelectItems('areas-de-especializacion');
    $operaciones = getSelectItems('operaciones');
    $titulos = getAllPostTitles();
?>

<form method="post" id="advanced-searchform" role="search" action="<?php echo esc_url( home_url( '/' ) ); ?>">
    <!-- PASSING THIS TO TRIGGER THE ADVANCED SEARCH RESULT PAGE FROM functions.php -->
    <input type="hidden" name="search" value="advanced">
    <input type="search" id="acexito" class="acexito search-field" name="s" placeholder="<?php _e( '¿qué estás buscando?...', 'textdomain' ); ?>" value="<?php get_search_query(); ?>"/>
    <button type="button" id="btnfiltros" class="btnfiltros btnclaro"></button>
    <div id="filtros" class="filtros">
        <div class="rowfilter">
            <label for="area" class="leftinput"><?php _e( 'Área', 'textdomain' ); ?></label>
            <select class="iptfiltro" name="area[]" id="area" multiple="multiple">
                <?php
                    for($i=0;$i<count($areas);$i++){      
                ?>
                        <option value="<?php echo $areas[$i]['id'];?>"><?php echo $areas[$i]['name'];?></option>
                <?php
                    }
                ?>
            </select>
        </div>
        <div id="rowcliente" class="rowfilter">
            <label for="cliente" class="leftinput"><?php _e( 'Cliente', 'textdomain' ); ?></label>
            <select class="iptfiltro" name="cliente[]" id="cliente" multiple="multiple">
                <?php
                    for($i=0;$i<count($clientes);$i++){      
                ?>
                        <option value="<?php echo $clientes[$i]['id'];?>"><?php echo $clientes[$i]['name'];?></option>
                <?php
                    }
                ?>
            </select>
        </div>
        <div id="rowsector" class="rowfilter">
            <label for="sector" class="leftinput"><?php _e( 'Sector', 'textdomain' ); ?></label>
            <!--<input type="text" name="sector" id="sector" class="iptfiltro"/>-->
            <select class="iptfiltro" name="sector[]" id="sector" multiple="multiple">
                <?php
                    for($i=0;$i<count($sectores);$i++){      
                ?>
                        <option value="<?php echo $sectores[$i]['id'];?>"><?php echo $sectores[$i]['name'];?></option>
                <?php
                    }
                ?>
            </select>
        </div>
        <div class="rowfilter">
            <label for="operacion" class="leftinput"><?php _e( 'Operación', 'textdomain' ); ?></label>
            <select class="iptfiltro" name="operacion[]" id="operacion" multiple="multiple">
                <?php
                    for($i=0;$i<count($operaciones);$i++){      
                ?>
                        <option value="<?php echo $operaciones[$i]['id'];?>"><?php echo $operaciones[$i]['name'];?></option>
                <?php
                    }
                ?>
            </select>
        </div>
        <div class="rowfilter fecha" id="rowini">
            <label for="fechaini" id="labelfecha" class="leftinput"><?php _e( 'Fecha', 'textdomain' ); ?></label>
            <!--<label id="labelini" for="fechaini" class="leftinput"><?php //_e( 'Inicio', 'textdomain' ); ?></label>-->
            <input type="text" name="fechaini" id="fechaini" class="iptfiltro" placeholder="<?php _e( 'Inicio', 'textdomain' ); ?>"/>
            <!--<label id="labelfin" class="leftinput"><?php //_e( 'Fin', 'textdomain' ); ?></label>-->
            <input type="text" name="fechafin" id="fechafin" class="iptfiltro" placeholder="<?php _e( 'Fin', 'textdomain' ); ?>"/>
        </div>
    </div>
    <input type="submit" id="submitsearch" class="submitsearch" value="Buscar"/>
</form>

Then, here is the content of my functions.php file

 //Obtain categories for preloading
    function getSelectItems($slugcategoria){
        $categoria = get_category_by_slug($slugcategoria);
        $args = array(
            'child_of'                 => $categoria->term_id,
            'orderby'                  => 'name',
            'order'                    => 'ASC',
            'hide_empty'               => FALSE,
            'hierarchical'             => 1,
            'taxonomy'                 => 'category'
        ); 
        $child_categories = get_categories($args);
        $items = array();
        foreach($child_categories as $cat){
            $desglose = array(
                'id' => $cat->cat_ID,
                'name' => $cat->name
            );
            array_push($items, $desglose);
        }
        return $items;
    }

function customSearchByParams($keywords,$clientes,$areas,$sectores,$operaciones,$fechaini,$fechafin){

    //Crear array de IDs de categoria previamente
    //Wordpress - fecha formato Y-m-d

    $cats = array();

    //Add "customers" to the query
    if(!empty($clientes)){
        for($i=0;$i<count($clientes);$i++){
            array_push($cats, $clientes[$i]);
        }
    }

    //Add "business areas" to the query
    if(!empty($areas)){
        for($i=0;$i<count($areas);$i++){
            array_push($cats, $areas[$i]);
        }
    }

    //Add "business sectors" to the query
    if(!empty($sectores)){
        for($i=0;$i<count($sectores);$i++){
            array_push($cats, $sectores[$i]);
        }
    }

    //Add items from "operation" subcategories
    if(!empty($operaciones)){
        for($i=0;$i<count($operaciones);$i++){
            array_push($cats, $operaciones[$i]);
        }
    }

    /*I check for "--" because my datepicker library sends "--" if nothing was selected*/

    //Filter by date
    if($fechaini=="--" && $fechafin=="--"){
        //No dates
        $args = array(
            'category__in' => $cats
        );
    }else if($fechaini!="--" && $fechafin=="--"){
        //Only posts after given date
        $partsini = explode("-", $fechaini);
        $args = array(
            'category__in' => $cats,
            'date_query' => array(
                array(
                    'after' => array(
                                    'year'  => $partsini[0],
                                    'month' => $partsini[1],
                                    'day'   => $partsini[2],
                                ),
                    'inclusive' => true
                )
            )
        );
    }else if($fechaini=="--" && $fechafin!="--"){
        //Only posts before given date
        $partsfin = explode("-", $fechafin);
        $args = array(
            'category__in' => $cats,
            'date_query' => array(
                array(
                    'before' => array(
                                    'year'  => $partsfin[0],
                                    'month' => $partsfin[1],
                                    'day'   => $partsfin[2], 
                                ),
                    'inclusive' => true
                )
            )
        );
    }else{
        //Both (date in between two given dates)
        $partsini = explode("-", $fechaini);
        $partsfin = explode("-", $fechafin);
        $args = array(
            'category__in' => $cats,
            'date_query' => array(
                array(
                    'after' => array(
                                    'year'  => $partsini[0],
                                    'month' => $partsini[1],
                                    'day'   => $partsini[2],
                                ),
                    'before' => array(
                                    'year'  => $partsfin[0],
                                    'month' => $partsfin[1],
                                    'day'   => $partsfin[2],
                                ),
                    'inclusive' => true,
                    'relation' => 'AND'
                )
            )
        );
    }

    if(!empty($keywords)){
        $args['s'] = $keywords;
        $words = explode(" ", $keywords);
        foreach($words as $word){
            $slug = slugify($word);
            $categoria = get_category_by_slug($slug);
            if(!empty($categoria)){
                array_push($cats, $categoria->cat_ID);
            }
        }
        $args['category__in'] = $cats;
    }

    $args['posts_per_page'] = 10;
    $args['nopaging'] = false;
    $args['paged'] = false;

    $the_query = new WP_Query($args);
    return $the_query;
}

This last function elaborates the WP_Query that I use later on and output with a template accordingly. The thing I want to get fixed is the Query, basically, I need it to be smart and powerful.

I've read the documentation, and tried some stuff myself. I wanted to stick to WP_Query, as I'm totally lost when it comes to the WP Database itself, I wanted to avoid using pure MySQL queries for fetching the posts.

How can I get this working? My current version works, but it could be done much better I think. Any advice is appreciated.

0

Alright folks, so APPARENTLY I managed to solve this myself.

This code was provoking the "Starbucks case" that I was explaining before

if(!empty($keywords)){
        $args['s'] = $keywords;
        $words = explode(" ", $keywords);
        foreach($words as $word){
            $slug = slugify($word);
            $categoria = get_category_by_slug($slug);
            if(!empty($categoria)){
                array_push($cats, $categoria->cat_ID);
            }
        }
        $args['category__in'] = $cats;
    }

I changed it to

if(!empty($keywords)){
        $args['s'] = $keywords;
    }

And now it works. It looks like the idea of searching if there was any category slugifying the words entered in the searchform was a bad idea (or at least, I was doing it wrong), because when I used category__in, I was forcing Wordpress to fetch ONLY the posts that had THAT TITLE and belonged to THE CATEGORY with the same name.

Problem solved :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.