2

I just want to make my CodeIgniter filter form work. For example, if "Samsung" is selected from the dropdown list and "2G" from the checkbox fields, then rows with id 1 and 4 should be returned. Currently my model returns nothing. I think the problem is in the if statement of the model, but I cannot find out what is the exact reason.

Here is my database table:

database table

Here is my filter form:

filter form

Here is My Model:

<?php
if (!defined('BASEPATH')) {
    exit('No direct script access allowed');
}
        
class Model_example extends CI_Model
{
    function __construct()
    { 
        parent::__construct();
    }
        
    public function did_filter()
    {
        $types = $this->input->post('types');
        
        $data = array(
            '2g' => 0,
            '3g' => 0,
            '4g' => 0,                
        );                  
        foreach ($types as $type) {
            $data[$type] == 1;
        }
        $this->db->select('*');
        $this->db->from('table_example');
        $this->db->where('phone', $this->input->post('phone'));
               
        if ($query = $this->db->get()) {
            if (
                (('2g' == 1) AND ($data['2g'] == 1)) OR
                (('3g' == 1) AND ($data['3g'] == 1)) OR  
                (('4g' == 1) AND ($data['4g'] == 1))
           ) {               
               return $result = $query->result_array();
           } else {
               return false;
           }            
       } else {
           return false;
       }
    }  
}

Here is My View number 1:

<?php 
$this->load->helper("form", "file");
echo validation_errors();              
echo form_open_multipart("example/search");
    
echo form_label("Phone:<br>", "phone");
$data = array(
    "" => "Select Phone",
    "samsung" => "Samsung",
    "htc" => "HTC",
    "nokia" => "Nokia",
);
echo form_dropdown('phone', $data, set_value('phone'));
    
echo br(5);
?> 
    
<?php echo form_label("Network Type:<br>", "type"); ?>                   
<input type="checkbox" name="types[]" value="2g" id="types" <?php echo set_checkbox('types[]', '2g', FALSE); ?>/>2G<br />
<input type="checkbox" name="types[]" value="3g" id="types" <?php echo set_checkbox('types[]', '3g', FALSE); ?>/>3G<br />
<input type="checkbox" name="types[]" value="4g" id="types" <?php echo set_checkbox('types[]', '4g', FALSE); ?>/>4G<br />
<br />

<?php
echo br(1);
echo form_submit("filterSearch", "Search");
    
echo form_close();
?>

Here is My View number 2:

<?php 
print_r($result);

Here is my controller:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
    
class Example extends MX_Controller {
    public function index() { //main function
        $this->load->view("view_example");
    }
    
    public function search() { 
        $this->load->library('form_validation');
        $this->load->model('model_example');
    
        $this->form_validation->set_rules('phone', 'Phone', 'required');
        $this->form_validation->set_rules('types[]', 'Network Type', 'required'); 
    
        if ($this->form_validation->run()) {
            $data["result"] = $this->model_example->did_filter();
            $this->load->view("view_search_results", $data); 
        } else {
            $this->load->view("view_no_search_results");
        }
    }
}
2
  • It won't return anything cause you placed return $result in an empty IF statement. Add those conditions in the where clause. Commented Mar 19, 2014 at 20:11
  • I already tried. It did not work. Commented Mar 20, 2014 at 15:53

3 Answers 3

3

Try this, it should work, i gave you two option for where so use the one that you need

 public function did_filter() {

    $types = $this->input->post('types');

    //list of types column name you can ignore this part by in cases someone change the value in html your query will fail so i am keeping this
    $data = array(
        '2g' => 0,
        '3g' => 0,
        '4g' => 0,
    );

    $this->db->select('*');
    $this->db->from('table_example');
    $this->db->where('phone', $this->input->post('phone'));

    // if you want to use and where use this block, or use the next block the is commented out
    foreach ($types as $type) {
        if (isset($data[$type])) { // this making sure that your column is correct 
            $this->db->where($type, 1);
        }
    }

    /**
    //If you want your checkbox to work as or, ie if 2g and 3g select and you want to show any check box match. 
    //In case of your example still it will give row 1 and 4, but if you use fist block it will give you row 1 only because row 1 got both 2g and 3g
    $or_where = array();
    foreach ($types as $type) {
        if (isset($data[$type])) { // this makeing sure that your colum is correct 
            $or_where[] = "$type = 1";
        }
    }
    if (count($or_where) > 0) {
        $where = implode(' OR ', $or_where); // make the or where for array
        $this->db->where("($where)");
    }
     * 
     */

    $query = $this->db->get();

    if ($query && $query->num_rows() > 0) {
        return $query->result_array();
    } else {
        return false;
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Hi Minhaz, thanks for your reply. I really appreciate your help. I want my checkbox to work as or, so I used the second block of your code but, unfortunately, there are several syntax errors for implode() function which I could not fix because it was a little bit complicated for me, could you please check it?
I modify the code, try this one, i made it fully simple it should work and you will able to understand to. Mainly the implode should give the query like $this->db->where("(2g=1 OR 3g=1)")
That's exactly what I wanted to do for several weeks :) You are the best :) Thank you very much Minhaz! I really appreciate your great support!
Hi Minhaz, Hope you are doing well :) Could you please have a look at my problem. Perhaps you can see my mistake. stackoverflow.com/questions/23976730/…
0

try this model

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class Model_example extends CI_Model
{

    function __construct()
    {
        parent::__construct();
    }

    public function did_filter()
    {
        $query = $this->db->get_where('table_example',array('phone' => $this->input->post('phone'),'types' => $this->input->post('types')));

        return $query->result_array();   
    }
}

Comments

0
  1. A model method should not be designed to directly access user input (superglobals). With very few exceptions, all data required by the model method should be passed in via method parameters or accessed as a class properties (depending on the implemented design pattern). Directly accessing superglobals/inputs, reduces the utility of a method and makes unit testing more difficult.

  2. Generally, model methods should not perform data preparations (the same rule applies to views). The lone responsibility of the model layer is to interact with data storage. The model should not perform business logic operations.

  3. Try to keep business logic processing and data preparations inside the controller method to a minimum -- "skinny" (brief/short/concise) controller methods should be the goal. The best controller methods look like a list of commands which are performed by other layers. Very seldom should controller methods "do any processing" themselves. Libraries can be a great place to write business logic operations. It is entirely reasonable for controller and library methods to call other layers such as models, libraries, and helpers. Helpers can be utilized for general data processing which is absent of any business logic.

  4. Design your methods with the intention of being called from multiple call sites in your application. Unless sacrificing utility for performance for specific cases, design your model methods for flexibility and maintainability.

Suggested model method:

public function get(array $brands = [], array $types = []): array
{
    if ($brands) {
        // one of the selected brands in the phone column
        $this->db->where_in('phone', $brands);
    }
    if ($types) {
        // 1 in at least one of the selected "g" columns
        $this->db->where_in(1, $types, false);
    }
    return $this->db
        ->get('table_example')
        ->result_array();
}

Notes:

  • select('*') never needs to be written in CodeIgniter because that is the default SELECT clause.
  • Since get() (as well as get_where()) can receive the tablename and is going to be called to execute the built query, omit the from() method from the call chain.
  • Although this script does not require any explicit value or identier quoting, see How to select rows where a single value is found in one of multiple columns using CodeIgniter's query-builder methods for the atypical implementation that uses explicit quoting with where_in() when the first parameter is the column value and the second parameter is an array of column names.
  • Do not conditionally return false from a method that ordinarily returns an array. This (too common) practice would require call sites to mitigate the possibility of processing a non-array data type before traversing the payload with an iterator. result_array() returns an array of zero or more arrays; if you want to check for an empty array, just make a falsey check on the array.

Your controller method can look like this:

public function search()
{ 
    $this->load->library('form_validation');
    $this->form_validation->set_rules('phone', 'Phone', 'required');
    $this->form_validation->set_rules('types[]', 'Network Type', 'required|in_list[2g,3g,4g]');
    
    if ($this->form_validation->run()) {
        $this->load->model('model_example', 'ModelExample');
        $data['result'] = $this->ModelExample->get(
            (array)$this->input->post('phone'),
            $this->input->post('types')
        );
        if ($data['result']) {
            $this->load->view('view_search_results', $data); 
        } else {
            $this->load->view("view_no_search_results");
        }
    }
}

Notes:

  • |in_list[2g,3g,4g] was added to set_rules() to validate the checkbox values against a whitelist of values correlating to database column names.
  • The model is only loaded if the form submission passed validation. Resources should only be instantiated if/when they are actually needed.
  • You might eventually like to make both phone and types form fields into multiselects or checkboxes. When that future comes, your model method will be ready.
  • I wouldn't create an additional view file just for "no results", I'd design my results view to accommodate zero or more results.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.