Try Tuts+ Premium, Get Cash Back!
CodeIgniter from Scratch: Search Results without Query Strings
videos

CodeIgniter from Scratch: Search Results without Query Strings

Tutorial Details
  • Topic: PHP
  • Difficulty: Intermediate - Advanced
  • Tut Format: Video
This entry is part 17 of 17 in the CodeIgniter From Scratch Session
« Previous

In this episode of CodeIgniter from Scratch, we will implement search features, and display the results pages without the use of query strings. You can use these methods to keep your URL’s clean, and continue using the uri segments convention of the CodeIgniter framework.

Press the HD button for a clearer picture.

Subscribe to our YouTube page to watch all of the video tutorials!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Ian

    I’ve been downloading these a few tuts ahead of where I actually am in the series. I’m about to start Day 9 but just dl’d Day 17 and was sad to see the end :-(

    Thank you Burak and Jefferey for the series. So far everything has worked perfectly for me and I understand both of you very well. I’m glad when you guys include the styling too because it helps me improve my css to see how you do it.

    I’m going to wait until I finish the series and then do as many others have and put it all together in my own site. I’ve been struggling to put together my own MVC and got started with the tinyMVC video but seeing how CI implements the concepts and where my app code fits in has been an awesome learning experience.

  • Hein Zaw Htet

    I want to clean all data in ci_query table after search. How to do that?

    • Jubic

      Go to phpmyadmin, and truncate the table.

  • Niccu

    More tutorial pleaseT.T this is a very good tutorial

  • teomor

    What point is there to do all that extra programming and EXTRA QUERIES, if you end up using the same GET variables later in the search function? Sorry, I just don’t get the idea..

  • prajan55

    suppose if I get an array as POST input, i am unable to loop through it and get all the array values and to store into query_array (i.e., store array within array).

    The snippets below:
    $query_array = array(
    ‘gender’ => $this->input->post(‘gender’),
    ‘minage’ => $this->input->post(‘minage’),
    ‘maxage’ => $this->input->post(‘maxage’),
    ‘Citizenship’ => $this->input->post(‘citizenship’), // checkboxes with name citizenship[]
    );

    This returns only last stored array value in Citizenship.

    The output array:

    Array ( [gender] => 1 [minage] => 18 [maxage] => 24 [Citizenship] => 2 )
    makes the query string as:

    &gender=1&minage=18&maxage=24&Citizenship=2
    But, my requirement is to get all the values of ‘Citizenship’ array instead of last stored value.

    The output required to make query string:

    Array ( [gender] => 1 [minage] => 18 [maxage] => 24 [Citizenship] => 2 [Citizenship] => 4 [Citizenship] => 6 )

    Any help appreciated.

    Thanks

  • Clumpster

    I find this approach too troublesome.

    First of all i totally disagree that using a uri form of “domain.name/search/123″ is better than say “domain.name/search/title/foo/category/bar” or even “domain.name/search?q=title=foo&category=bar”.

    All three options are permalinks (although there is no permalink in a search function since searches even with the same criteria can return different results over time). So, the two latter options are way more human readable which is always a good thing and SEO-wise i think it may be better also.

    If you’re going with database query for the search then the last thing you want is to add extra costly insert operations. You need a very good reason to add this much performance penalty to a site. Remember guys, every public input box must always be considered an easy target for spam bots (even if they don’t usually go for the search boxes) and should be protected in one way or another e.g by caching the results or doing lightweight operations.

    Lastly, the database needs to deal with duplicate queries (extra but necessary hassle).

    Anyway, i totally applause you for making these tutorials, i think they’re invaluable to the codeigniter community. It’s that i have complaints with this particular approach although i understand the need for permanent search urls.

    Thanks again for contributing to the codeigniter community and being a teacher to many of us!

  • http://www.ceblehsoft.net78.net Sigit Purnomo

    I have a problem,

    Data which saved into database is different from the tutorial.
    “&” is saved to be &

    example :
    “title=ACADEMY&category=Animation&length_comparison=gt&length=”
    should be
    “title=ACADEMY&category=Animation&length_comparison=gt&length=”

    what shall I do?

    Thank you and regards,
    Sigit

  • Sigit Purnomo

    @Clumpster

    I think your opinion is true.

    Sorry, I’m new comer in Codeigniter, I’m trying to make a searching with pagination, but I’m confused how to make searching with pagination in codeigniter, in normally PHP I used GET method.
    Could you give me some tutorial for searching with pagination like “domain.name/search/123″ is better than say “domain.name/search/title/foo/category/bar” or even “domain.name/search?q=title=foo&category=bar” ?

    With method that you mentioned, searching can be done without saving criteria to database.

    Thank you very much for your help.

    Regards,
    Sigit

  • pabix

    More tutorial please ;) ;)

  • Desmond Li

    It’s really a great series !!!

    Please continue !!

    Thanks a lot.

  • http://meetm8.com meetm8

    Worst tutorial I have seen on this website so far….. why database??

    • http://www.facebook.com/reginaldo.gutter Reginaldo Gutter

      Why database? Since you’re passing data through POST, how would an user save his search on Favorites? How about him sending it to a friend?

      There are other solutions, like saving the data on sessions, but the user won’t be able to Favorite it or send to someone. Other solution would be passing it to the URL. But, you will have a messy URL and depending on the size of the form you’re working with, you wouldn’t be able to pass all the information. And more: What about websites in portuguese, where you have lots of special chars like á, é, ó, í, ú… Maybe if you encode it, but it would cause you some problem.

      This is a great tutorial. Of course is not a implementable solution, but is a great start.

  • http://nguyentoancomptia.com MrPeo

    I got thí error when run my site on host: Call to undefined method MY_Input::load_query(). I used CI 2.0.
    Can any body help me?

    • RyanS

      I am getting “Call to undefined method CI_Input::load_query” … frustrating!

  • Aiman yuuhi

    i keep getting these error

    Fatal error: Call to undefined method CI_Input::load_query() in C:\wamp\www\cituto\ci_day17\application\controllers\films.php on line 19

  • anthony

    anyone notice that only the first search fields work in this case you can only search by title not
    category nor length..

  • Tim

    I really need your help. I was introduced to codeigniter recently and find this tutorial really useful. but I’m now puzzled with the following error even if I’ve followed everything as taught in the video
    I get the error when implementing the search facility
    Fatal error: Call to undefined method CI_Input::load_query() in /var/www/html/dev/TM/codeigniter/application/controllers/tasks.php on line 27

  • Milos

    the best tutorial I’ve seen so far….

  • http://www.dragonsdesign.co.uk Chris Ward

    I’m new to codeigniter too but from what i can see The CI_Input::load_query() error is due to there being no input library in the system folder to extend from. Although it’s in the official docs.

    Just put the methods in your model and call $this->Form_model->load_query() instead

    • Enrico Perez

      Alternatively, you could put the MY_Input.php on the application/core folder.

    • Jahanzeb Khan

      CI 2 moved the input library to the core folder, so you have to make MY_Input.php in application/core.

  • http://only-1.co.za Alexander

    Loved every single tutorial, happy to be on my way with CI Framework.

    Only problem I have with this method of storing the search query in a DB is the same search is stored under a different ID.

    e.g if I search Category -> Action more then once it will store both search’s and give them different ID’s. Would be nice if there was a way to check, hey this search query has happened before return the ID to the query search. I will work on this…

    Thanks for the Tutorials!

    • http://www.only-1.co.za Alexander van Zyl

      Below is my solution to the said above:

      function save_query($query_array) {

      $CI =& get_instance();

      $rows = $CI->db->get_where(‘ci_query’, array(‘query_string’ => http_build_query($query_array)))->result();

      if($rows[0]) {

      $this->load_query($rows[0]->id);
      return $rows[0]->id;

      } else {

      $CI->db->insert(‘ci_query’, array(‘query_string’ => http_build_query($query_array)));

      return $CI->db->insert_id();
      }
      }

  • Vadim

    Superb, never thought in that way.
    If there only we can check fast, for the same search query, so we don’t need to generate another query id.

  • Jahanzeb Khan

    Hey, I’d be really interested if anyone could suggest another place instead of the database to store these queries, because then some1 could spam the db just by keep on searching, and it’s terrible because it would take massive space.

    So if anyone can think of an alternative place to store this query stuff thats going in to the database, I’d love to know, just reply!

    • Andres

      I put my solution in the bottom ;)

  • deniel

    hii Burak ,

    your tutorials show very details explanation and also easy to understand , amazing for me .

    before that , i want to say thank you so much…

    Question :
    ========
    I had a problem on extending the input class (or libraries) , especially on save_query()

    browser display warning:
    =====================
    Fatal error: Call to undefined method CI_Input::load_query() in C:\xampp\htdocs\ci\application\controllers\films.php on line 23

    MY_Input.php (on, application/libraries/ )
    ===========
    class MY_Input extends CI_Input{

    function save_query($query_array)
    {
    //print_r($query_array);

    $CI =& get_instance();

    $CI->db->insert(‘ci_query’,
    array(‘query_string’ => http_build_query($query_array)));

    return $CI->db->insert_id();
    }

    }

    films.php (on, application/controllers/ )
    ===========
    function search()
    {
    $query_id = $this->input->save_query($query_array);
    }

    regards

    deniel

    • http://www.abneralvarado.com/ Abner Alvarado

      You should save your MY_Input.php file inside ‘application/core’ folder.

      Regards!

      • Rafiq Islam

        thanks, but show this error…

        A Database Error Occurred
        Error Number: 1146
        Table ‘sakila.ci_query’ doesn’t exist
        SELECT *
        FROM (`ci_query`)
        WHERE `id` = 0
        Filename: C:xampphtdocscodeIgniter_sortingsystemdatabaseDB_driver.php
        Line Number: 330

  • Ruffles

    Hey!

    Great Tutorial!

    I have a problem with the searching and I don’t know why! I am using version 2.1.2!

    The problem is when I use print_r to check for the query_array (around 24:30 mins in the video), I get an empty array with just values like: Array ( [title] => [category] => [length] => ) instead of text/numbers after =>.

    when I use print_r (parse_str($rows[0]->query_string, $_GET)); I don’t get anything, but when I use print_r($rows[0]->query_string) I get the string.

    There’s a problem with the parse_str() function in MY_input.php , the load_query() function.

    Please help!

    Thanks!

  • Ruffles

    Also I forgot to mention that instead of extending the input class , the functions are in the model and I am calling them using $this->name_model->load_query($query_id).

  • Andres

    Nice tutorial but just thinking in a real live project, with thousands of people visiting the page and using the search the amount of data in the database can be a mess. I think it may be better to use sessions instead of databases.

  • Andres

    Ok this is my solution with sessions instead databases.

    In the Films controller:
    ———————–

    function display($query_id = ”, $sort_by = ‘title’, $sort_order = ‘asc’, $offset = 0) {

    //The rest of the code
    //$this->Film_model->load_query($query_id); // Old system with the database
    $this->_load_session($query_id);

    // Here more code…
    }

    The search function in the class controller:
    ————————–

    function search() {
    // Old code here…
    $query_search = $this->_save_session($query_array);
    redirect(“films/display/search”);
    }

    Save session method:
    ————————–
    function _save_session($query_array) {
    $this->session->set_userdata(‘search’, http_build_query($query_array));
    }

    Load session method:
    ————————–
    function _load_session($search_query) {
    if(!is_null($search_query) && $search_query == “search”) {

    $search = $this->session->userdata(‘search’);

    if(isset($search)) {
    parse_str($search, $_GET);
    }
    }
    }
    ——————————–
    Maybe is not the best option but work well, and is another alternative to store the query string.

  • Amar

    Very nice Tutorials, you guys rock ,, \m/

  • Aikon

    buen tutorial

  • bcat

    awesome series, thanks Burak!

    Quick fix to avoid infinite DB inserts and make this solution implementable:
    one more char field “hash” (unique index) can be added to the queries table. Then if the logic from following pseudo code implemented in save function of input library it will only insert unique queries and be able to quickly check if the query is already in db:
    q_hash = md5($query);
    result = db->get(‘hash’, q_hash));
    if (result->num_rows()) {return result->id;}
    else {save new query and its hash in db, return the new id as in screencast}

  • Sridhar

    can any one tell about the below query?
    after inserting the values in to db i want to dispaly a message in the view as “inserted successfully”?
    how it is possible in codeigniter.

  • Guest

    cvxccxvcx

  • Sridhar

    hi all, ia m using codeigniter to insert form values into db, after inserting the form values,i need to show a success message in the same view..
    any help will be appreciated.

  • ahmed

    kjl

  • ahmed mazari

    I have a problem when running films/display ,someone to help me

    l made MY_Input class in application/core/MY_Input.php
    the error is shown like below:

    A PHP Error was encountered

    Severity: Notice

    Message: Undefined offset: 0

    Filename: core/MY_Input.php

    Line Number: 12 (the error in this line if ($rows[0]){ )

    A Database Error Occurred

    Error Number: 1054

    Unknown column ’0′ in ‘order clause’

    SELECT `FID`, `title`, `category`, `length`, `rating`, `price` FROM (`film_list`) ORDER BY `0` asc LIMIT 20, 1

    Filename: C:wampwwwcodeignitersystemdatabaseDB_driver.php

    Line Number: 330

    this my code source of MY_Input class
    db->insert(‘ci_query’,array(‘query_string’ => http_build_query($query_array)));

    return $CI->db->insert_id();

    }

    function load_query($query_id){

    $CI =& get_instance();

    $rows = $CI->db->get_where(‘ci_query’,array(‘id’=>$query_id))->result();

    if ($rows[0]){

    parse_str($rows[0]->query_string,$_GET);

    } } }

    this is my controller films

    ‘ID’,

    ‘title’ => ‘Title’,

    ‘category’ => ‘category’,

    ‘length’ => ‘length’,

    ‘rating’ => ‘rating’,

    ‘price’ => ‘price’

    );

    $this->input->load_query($query_id);

    // $this->film_model->load_query($query_id); // Old system with the database

    //$this->_load_session($query_id);

    $query_array = array(

    ‘title’ => $this->input->get(‘title’),

    ‘category’ => $this->input->get(‘category’),

    ‘length_comparison’ => $this->input->get(‘length_comparison’),

    ‘length’ => $this->input->get(‘length’)

    );

    // print_r($query_array);return;

    $this->load->model(‘film_model’);

    $results = $this->film_model->search($query_array,$limit, $offset,$sort_by,$sort_order);

    $data['films'] = $results['rows'];

    $data['num_results'] = $results['num_rows'];

    $this->load->library(‘pagination’);

    $config = array();

    $config['base_url'] = site_url(“films/display/$sort_by/$sort_order”);

    $config['total_rows'] = $data['num_results'];

    $config['per_page'] = $limit;

    $config['num_links'] = 15;

    $config['uri_segment'] = 5;

    $this->pagination->initialize($config);

    $data['pagination'] = $this->pagination->create_links();

    $data['sort_by'] = $sort_by;

    $data['sort_order'] = $sort_order;

    $data['category_options'] = $this->film_model-> category_options();

    $this->load->view(‘films’,$data);

    }

    function search(){

    $query_array = array(

    ‘title’ => $this->input->post(‘title’),

    ‘category’ => $this->input->post(‘category’),

    ‘length_comparison’ => $this->input->post(‘length_comparison’),

    ‘length’ => $this->input->post(‘length’),

    );

    $query_id = $this->input->save_query($query_array);

    redirect(“films/display/$query_id”);

    }

    }