Question

I want to build an ajax searc filters with dropdown select boxes. I will try to be as much clear as i can.

I have a Typology Model and controller. A typology has

id | title | description | item_id | condition_id | category_id | condition_id | price

where id is primary key and item_id, condition_id, category_id, condition_id are foregin keys.

So when typology index page is loaded it shows a list of all typologies.

Search Form is as follow:

<form name="search_form" id="search_form">  
                <li><p>tipologia</p>                     
                <?php    
                echo "<select name=\"typology_categories\" class=\"select_filter\" >";
                echo "<option value=''>All</option>";
                    foreach ($typologyCategories as $typologyCategory): 
                        $category_id = $typologyCategory['TypologyCategory']['id'];
                        $category_name = $typologyCategory['TypologyCategory']['name'];
                        echo "<option value='{$category_id}'>{$category_name}</option>";
                    endforeach;
                echo "</select>";                                   
                ?>
                </li>

                <li><p>localita</p>
                <?php 
                echo "<select name=\"item_locations\" class=\"select_filter\">";
                echo "<option value=''>All</option>";
                    foreach ($itemLocations as $itemLocation): 
                        $item_id = $itemLocation['ItemLocation']['id'];
                        $item_name = $itemLocation['ItemLocation']['name'];
                        echo "<option value='{$item_id}'>{$item_name}</option>";
                    endforeach;
                echo "</select>";
                ?>
                </li>
                <li><p>prezzo</p>
                    <select name="typology_price" class="select_filter">
                        <option value="">All</option>
                        <option value="1">0 - 1,000</option>
                        <option value="2">1,000 - 5,000</option>
                        <option value="3">5,000 - 50,000</option>
                        <option value="4">50,000 - 100,000</option>
                        <option value="5">100,000 - 500,000</option>
                        <option value="6">500,000 - 1,000,000</option>
                        <option value="7">more then 1,000,000</option>
                    </select>
                </li>
                <li><p>stato</p>
                <?php 
                echo "<select name=\"typology_conditions\" class=\"select_filter\">";
                echo "<option value=''>All</option>";
                    foreach($typologyConditions as $typologyCondition):
                        $condition_id = $typologyCondition['TypologyCondition']['id'];
                        $condition_name = $typologyCondition['TypologyCondition']['name'];
                        echo "<option value='{$condition_id}'>{$condition_name}</option>";
                    endforeach;
                echo "</select>";
                ?>
                </li>
                </form>

The ajax call is:

    <!-- HERE IS THE SEARCH FILTER -->
    <script type="text/javascript" >
        $(document).ready(function () {
            $('.select_filter').bind("change keyup input",function() {
              $.ajax({
                   type: "POST",
                   url: "search.php", // This one should sent data to index action of the typology controller for processing
                   data: $("#search_form").serialize(), 
// You will get all the select data..
                    success:function(data){
                        $("#projects").html(data);
                    }
                });
          });
        });
    </script>

Typology Controller is this: index action:

/**
 * index method
 *
 * @return void
 */
    public function index() {
        $this->set('title_for_layout', 'CESI');
        $this->layout='Homepage';

             // Typology Query
        $typologies = $this->Typology->find('all', array('recursive'=>-1, 'order' => array('Typology.' . $this->Typology->primaryKey . ' DESC')));
        $this->set('typologies', $typologies);

             // Typology Category Query
        $typologyCategories = $this->TypologyCategory->find('all', array('recursive'=>-1));
        $this->set('typologyCategories', $typologyCategories);
             // Typology Condition Query

        $typologyConditions = $this->TypologyCondition->find('all', array('recursive'=>-1));
        $this->set('typologyConditions', $typologyConditions);

            // Item Query       
        $items = $this->Item->find('all',array('recursive'=>-1));
        $this->set('items', $items);

            // Item Location Query
        $itemLocations = $this->ItemLocation->find('all', array('recursive'=>-1));
        $this->set('itemLocations', $itemLocations);

            // Slider Query
        $sliders = $this->Slider->find('all', array('recursive'=>-1));
        $this->set('sliders', $sliders);
    } 

So the Query that i wanna use for the search that i build is this:

<?php 
  /* Query for the Typology*/
          $queryTypologies = "SELECT * ";
          $queryTypologies .= "FROM typologies";
          $queryTypologies .= " WHERE  1=1 ";

        if (isset($_POST['typology_categories']) && !empty($_POST['typology_categories']) && $_POST['typology_categories']!='') {
           $queryTypologies .= " AND typology_category_id = (SELECT id FROM typology_categories WHERE id ='".trim(mysql_prep($_POST['typology_categories']))."' LIMIT 1)";
        }

        if (trim($_POST["item_locations"])!='' && !empty($_POST['item_locations'])) {
            $queryTypologies .= " AND item_id = (SELECT id FROM items WHERE item_location_id ='".trim(mysql_prep($_POST['item_locations']))."' LIMIT 1)";   //'".trim(mysql_prep($_POST['item_locations']))."'
        }
                            // value="1" 0         - 1,000
                            // value="2" 1,000     - 5,000
                            // value="3" 5,000     - 50,000
                            // value="4" 50,000    - 100,000
                            // value="5" 100,000   - 500,000
                            // value="6" 500,000   - 1,000,000
                            // value="7" more then - 1,000,000

        if (trim($_POST["typology_price"])!='' && !empty($_POST['typology_price']) && $_POST['typology_price']!='') {

            if (trim($_POST["typology_price"]) == 1) {  
                $queryTypologies .= " AND price <= 1000";                           
            }
            if (trim($_POST["typology_price"]) == 2) {  
                $queryTypologies .= " AND price BETWEEN 1001 AND 5000";                         
            }
            if (trim($_POST["typology_price"]) == 3) {  
                $queryTypologies .= " AND price BETWEEN 5001 AND 50000";                            
            }
            if (trim($_POST["typology_price"]) == 4) {  
                $queryTypologies .= " AND price BETWEEN 50001 AND 100000";                          
            }
            if (trim($_POST["typology_price"]) == 5) {  
                $queryTypologies .= " AND price BETWEEN 100001 AND 500000";                         
            }
            if (trim($_POST["typology_price"]) == 6) {  
                $queryTypologies .= " AND price BETWEEN 500001 AND 1000000";                            
            }
            if (trim($_POST["typology_price"]) == 7) {  
                $queryTypologies .= " AND price > 1000000";                         
            }
        }


        if (trim($_POST["typology_conditions"])!='' && !empty($_POST['typology_conditions']) && $_POST['typology_conditions']!='') {
            $queryTypologies .= " AND typology_condition_id = '".trim(mysql_prep($_POST['typology_conditions']))."' ";  
        }

          $typologies = mysql_query($queryTypologies) or die (mysql_error());

            $numrows = mysql_num_rows($typologies);
                        if($numrows != 0){
                                $result ="";
                                    while($rowTypologies= mysql_fetch_assoc($typologies)){

                                        $id                    = $rowTypologies['id'];
                                        $item_id               = $rowTypologies['item_id'];
                                        $title                 = htmlentities($rowTypologies['title'], ENT_COMPAT, "UTF-8");
                                        $description           = htmlentities($rowTypologies['description'], ENT_COMPAT, "UTF-8");
                                        $thumbnail             = htmlentities($rowTypologies['thumbnail'], ENT_COMPAT, "UTF-8");
                                        $price                 = htmlentities($rowTypologies['price'], ENT_COMPAT, "UTF-8");
                                        $typology_category_id  = htmlentities($rowTypologies['typology_category_id'], ENT_COMPAT, "UTF-8");
                                        $typology_condition_id = htmlentities($rowTypologies['typology_condition_id'], ENT_COMPAT, "UTF-8");

                                         if (strlen($description)>303) {
                                            $short_description = substr($description, 0, 300);
                                            $description = $short_description."...";
                                         }

                                        $first = base64_encode($item_id);
                                        $typologyThumbnails = "admin/app/webroot/img/uploads/typology/thumbnails/" . $thumbnail;
                                        $result .= "<div class=\"item_shadow\">";
                                        $result .= "<div class=\"item\" style=\"background-image:url({$typologyThumbnails});\">";
                                        $result .=  "<div class=\"item-content\">";
                                        $result .=      "<div class=\"item-top-content\">";
                                        $result .=          "<div class=\"item-top-content-inner\">";
                                        $result .=              "<div class=\"item-top-title\">";
                                        $result .=                      "<h4>{$title}</h4>";
                                        $result .=              "</div>";
                                        $result .=          "</div>"    ;
                                        $result .=      "</div>";
                                        $result .=      "<div class=\"item-add-content\">";
                                        $result .=          "<div class=\"item-add-content-inner\">";
                                        $result .=              "<div class=\"description-inner\">";
                                        $result .=                  "<p>{$description}</p>";
                                        $result .=              "</div>";
                                        $result .=              "<div class=\"read-more-inner\">";
                                        $result .=                  "<a href=\"new.php?id=$first\">maggiori informazioni <img src=\"img/elenco.png\"/></a>";
                                        $result .=              "</div>";
                                        $result .=          "</div>";
                                        $result .=      "</div>";
                                        $result .=  "</div>";
                                        $result .= "</div>";
                                        $result .= "</div>";

                                    }
                                echo $result;
                            } else {
                            echo "No Result Found in Database.";
                        }    
 ?>

I know this works because first i build it on raw php coding as you can see by yourselfs, and it worked perfect but now i want to implement it on cakephp. And i havent found a way yet.

Any help would be much appruciated!

Thanx in advance

Was it helpful?

Solution

As i Searched Through tutorials and Cakephp Cook Book. The best uproach i reached is this:

First: The thing that was preventing the aJax to do the Search was the Security Component. Since Forms in cakephp generate a unique token. Each time it is submited should be a different one so since i was using ajax it was generating error. so i disabled

public function beforeFilter() {    
     parent::beforeFilter();
        // Controller spesific beforeFilter
        $this->Auth->allow('search');
         if ($this->action == 'search') {
            $this->Security->validatePost = false;
            $this->Security->csrfCheck = false;

            if (!$this->RequestHandler->isAjax()) {
                $this->Security->blackHole($this, 'You are not authorized to process this request!');
                $this->redirect(null, 401, true);
            } 
        }
    }

Then i used the query(); method of cakephp since my query was complex and it used Joins and Conditions as well. So the search() function is as follow.

app/Controllers/ControllerName

/**
 * aJax search method
 *
 * @return void
 */
    public function search() {
    $this->autoRender = false;
        if ($this->request->is('post')) {
            if(!empty($this->data)){
                if ($this->request->is('ajax')) {

          /* Query for the Typology*/
          $queryTypologies  =" SELECT *";
          $queryTypologies .=" FROM typologies AS Typology";
          $queryTypologies .=" LEFT JOIN items as Item";
          $queryTypologies .=" ON Item.id = Typology.item_id";
          $queryTypologies .=" WHERE Item.published=1 AND Typology.published=1";          

        if (isset($this->data['Typology']['typology_categories']) && !empty($this->data['Typology']['typology_categories']) && $this->data['Typology']['typology_categories']!='') {
           $queryTypologies .= " AND Typology.typology_category_id ='".$this->request->data['Typology']['typology_categories']."'";
        }
        if (trim($this->data['Typology']['item_locations'])!='' && !empty($this->data['Typology']['item_locations']) && $this->request->data['Typology']['item_locations']!='') {
            $queryTypologies .= " AND Typology.item_id=(SELECT id FROM items AS Item WHERE Item.item_location_id='".$this->request->data['Typology']['item_locations']."' LIMIT 1)";
        }
        if (trim($this->request->data['Typology']['typology_price'])!='' && !empty($this->request->data['Typology']['typology_price']) && $this->request->data['Typology']['typology_price']!='') {

            if (trim($this->request->data['Typology']['typology_price']) == 1) {    
                $queryTypologies .= " AND Typology.price <= 1000";                          
            }
            if (trim($this->request->data['Typology']['typology_price']) == 2) {    
                $queryTypologies .= " AND Typology.price BETWEEN 1001 AND 5000";                            
            }
            if (trim($this->request->data['Typology']['typology_price']) == 3) {    
                $queryTypologies .= " AND Typology.price BETWEEN 5001 AND 50000";                           
            }
            if (trim($this->request->data['Typology']['typology_price']) == 4) {    
                $queryTypologies .= " AND Typology.price BETWEEN 50001 AND 100000";                         
            }
            if (trim($this->request->data['Typology']['typology_price']) == 5) {    
                $queryTypologies .= " AND Typology.price BETWEEN 100001 AND 500000";                            
            }
            if (trim($this->request->data['Typology']['typology_price']) == 6) {    
                $queryTypologies .= " AND Typology.price BETWEEN 500001 AND 1000000";                           
            }
            if (trim($this->request->data['Typology']['typology_price']) == 7) {    
                $queryTypologies .= " AND Typology.price > 1000000";                            
            }
        }
        if (trim($this->data['Typology']['typology_conditions'])!='' && !empty($this->data['Typology']['typology_conditions']) && $this->data['Typology']['typology_conditions']!='') {
            $queryTypologies .= " AND Typology.typology_condition_id='".$this->request->data['Typology']['typology_conditions']."'";    
        }
        $queryTypologies .=" ORDER BY Typology.id DESC";

                    $typologies = $this->Typology->query($queryTypologies);    
                    $this->set('typologies', $typologies);
                    /* debug($this->data); // This is used for development purposes ONLY!  */

                    if($this->RequestHandler->isAjax()){                        
                        $this->render('search', 'ajax');    
                    }               
                }
            }

        }
    }

And in the View i used this Ajax:

<!-- HERE IS THE SEARCH FILTER -->
 <script type="text/javascript" >
 //<![CDATA[
    $(document).ready(function () {
        $('.select_filter').bind('change keyup input',function(event) {
            $('html,body').animate({ scrollTop: $("#work").offset().top}, "slow");
            var formData = $('#search_form').serialize(); 
            $.ajax({
                async:true, 
                data: formData, // You will get all the select data..
                dataType:'html',
                success:function(data){
                    $("#projects").html(data);
                },
                type: 'POST',
                url:'<?php echo Router::Url(array('controller' => 'typologies','admin' => false, 'action' => 'search'), true); ?>'
            });
            event.preventDefault();
            return false;
        });
    });
//]]>
 </script>

This worked as charm for me. Feel free to use it. i hope it would be handy for anyone.

OTHER TIPS

The find I suppose you can do it normally, as you did it on the index() page. Seems that you have trouble with returning the ajax response to the client.

For this, you can use json views, so you can do the search on the controller (in search() method) and the render in the view, and returning it as an ajax response, instead of all on the same place as you have it in your native PHP code.

Please take a look at this link for how to use it: http://book.cakephp.org/2.0/en/views/json-and-xml-views.html#using-a-data-view-with-view-files

public function beforeFilter() {    
 parent::beforeFilter();
    // Controller spesific beforeFilter
    $this->Auth->allow('search');
     if ($this->action == 'search') {
        $this->Security->validatePost = false;
        $this->Security->csrfCheck = false;

        if (!$this->RequestHandler->isAjax()) {
            $this->Security->blackHole($this, 'You are not authorized to process this request!');
            $this->redirect(null, 401, true);
        } 
    }
}

function is helpful for beginer in code with CakePHP 2, it's have got a parent function with backgroud runtime.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top