简体   繁体   English

如何在CodeIgniter 2.1的数据库API中实现搜索和分页?

[英]How to implement search and pagination in CodeIgniter 2.1's database API?

I am having trouble with a search feature on a site I built with Codeigniter 2.1. 我在使用Codeigniter 2.1构建的网站上无法使用搜索功能。 Specifically, I am having trouble with pagination and limiting to 15 items per page. 具体来说,我在分页上遇到麻烦,每页限制为15个项目。

My controller: 我的控制器:

              public function program_search()
          {
      if ($this->input->post('term')){
        $this->front->set('title', 'Search Results');
        $this->front->set('res' ,  $this->wc_search->search($this->input->post('term')));

        $this->load->library('pagination');

        $config['base_url'] = base_url().'/site/program_search_results/';

        $this->db->where('JobRef',$this->input->post('term'));
        $this->db->or_where('WorkType',$this->input->post('term'));
        $this->db->or_where('Parish',$this->input->post('term'));
        $this->db->or_where('Location',$this->input->post('term'));

        $config['total_rows'] = $this->db->count_all_results('wc_program');
        $config['per_page'] = 10;
        $config['num_links'] = 20;
        $config['full_tag_open'] = '<div id="pagination">';
        $config['full_tag_close'] = '</div>';

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

        $this->front->buffer('content', 'site/program_search_results');
        $this->front->render();
    }
    else
    {
        $this->front->set('title', 'Program Search');
        $this->front->buffer('content', 'site/program_search');
        $this->front->render();
    }
}

Then in my model I have: 然后在我的模型中,我有:

            public function search($term)
        {
    $data = array();
    $this->default_select();
    $this->db->like('JobRef', $term);
    $this->db->or_like('Area', $term);
    $this->db->or_like('Parish', $term);
    $this->db->or_like('WorkType', $term);
    $this->db->or_like('Location', $term);

    $this->default_order_by();
    //$this->db->limit(15);
    $q = $this->db->get('wc_program');
        if ($q->num_rows() > 0)
        {
            foreach ($q->result_array() as $row)
            {
                $data[] = $row;
            }
        }
    $q->free_result();
    return $data;
}

How do I get the pagination to work based on this code? 如何根据此代码进行分页工作? I don't really want to alter the code already there as the search works fine. 我真的不想更改已经存在的代码,因为搜索效果很好。 I just need it to show 15 records per page for whatever term is searched for. 我只需要它在每页搜索中显示15条记录即可。

Let's see if I can walk you through the issues: 让我们看看我是否可以指导您解决这些问题:

  1. Your search query needs a LIMIT (which you have commented out...and it's missing the offset...). 您的搜索查询需要一个LIMIT(您已将其注释掉...并且缺少偏移量...)。
  2. You need to pass your POST page parameter ( $this->input->post('page') ) to your search model, so you know which page you are on, in order to compute the LIMIT part of your search model's query. 您需要将POST页面参数( $ this-> input-> post('page') )传递给搜索模型,以便知道您所在的页面,以便计算搜索模型查询的LIMIT部分。 Let's say you call it $current_page in your model. 假设您在模型中将其称为$ current_page
  3. Why does your count_all_results query not match your search model's query? 为什么您的count_all_results查询搜索模型的查询不匹配 They should match with the same WHERE conditions (except the count query would not have the LIMIT you are going to add to the search model's query). 它们应与相同的WHERE条件匹配(除了count查询不具有要添加到搜索模型查询中的LIMIT)。
  4. To compute the LIMIT (limit and offset): 计算 LIMIT(极限和偏移量):
    1. $limit = 15; $ limit = 15;
    2. $offset = $limit * $current_page - $limit; $ offset = $ limit * $ current_page-$ limit;
    3. if($offset < 0){$offset = 0;} if($ offset <0){$ offset = 0;}
  5. Now your limit is: $this->db->limit($offset, $limit); 现在您的限制为: $ this-> db-> limit($ offset,$ limit); for the search model's query. 搜索模型的查询。

Hope that helps! 希望有帮助!

Pass your per_page & num_links into the search() to calculate a LIMIT & OFFSET for your query 将您的per_page和num_links传递到search()中以计算查询的LIMIT&OFFSET

You'll need to do some simple math to calculate the offset 您需要做一些简单的数学计算偏移量

As David Graham says, you're missing your LIMIT and OFFSET. 正如David Graham所说,您错过了LIMIT和OFFSET。 The CodeIgniter pagination is fairly basic, since the underlying "ActiveRecord" is itself very basic (in essence, a query builder, NOT an ORM). CodeIgniter分页是相当基本的,因为底层的“ ActiveRecord”本身是非常基本的(本质上是查询生成器,而不是ORM)。

So, you need to think on the SQL level, how do you get "pages" of results that you want. 因此,您需要在SQL级别上思考如何获得所需结果的“页面”。

Below I am including sample code from one of my projects. 下面,我包括一个项目的示例代码。

CONTROLLER: 控制器:

    // set up pagination

    $itemsPerPage = 20;
    $totalItems = $this->Location_model->count_locations( $locationName, $locationType, $locationParent );

    // get itemStartIndex from URL if specified, otherwise default to 0
    if ( $this->uri->segment(3) )
    {
        $itemStartIndex = $this->uri->segment(3);
    }
    else
    {
        $itemStartIndex = '0';
    }

    $this->load->library('pagination');

    $config['base_url'] = site_url('admin/locations');
    $config['total_rows'] = $totalItems;
    $config['per_page'] = $itemsPerPage;
    $config['uri_segment'] = 3;

    // store offset in case user triggers a function and we want to come back to same page
    $this->session->set_flashdata('pagination_offset', $itemStartIndex);

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

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

    // get current locations from database
    $records = $this->Location_model->get_locations( $locationName, $locationType, $locationParent, $itemStartIndex, $itemsPerPage );

    ...

    // now $records gets passed to view for display

MODEL: 模型:

function count_locations($locationName = '', $locationType = '', $locationParent = '')
{
    $this->db->select('id');
    if ( $locationName != '' )
    {
        $this->db->like('name', $locationName);
    }
    if ( $locationType != '')
    {
        $this->db->where('location_type', $locationType);
    }
    if ( $locationParent != '')
    {
        $this->db->where('parent_id', $locationParent);
    }

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

    return $query->num_rows();
}

function get_locations($locationName = '', $locationType = '', $locationParent = '', $startIndex = '0', $limit = '')
{
    $this->db->select('*');
    if ( $locationName != '' )
    {
        $this->db->like('name', $locationName);
    }
    if ( $locationType != '')
    {
        $this->db->where('location_type', $locationType);
    }
    if ( $locationParent != '')
    {
        $this->db->where('parent_id', $locationParent);
    }

    $this->db->order_by('name', 'asc');
    $query = $this->db->get('locations', $limit, $startIndex);

    if ($query->num_rows() > 0)
    {
        return $query;
    }
    else
    {
        return FALSE;
    }
}

Notice that my method to do the query has the optional parameters $startIndex and $limit. 请注意,我执行查询的方法具有可选参数$ startIndex和$ limit。 These are MANDATORY for paging to work. 这些是分页工作所必需的。 The URI segment (in my case, segment 3) is going to directly tell your controller what OFFSET to use, and the per_page that you specify translates to the LIMIT (which in my case I use $itemsPerPage to store since it's referenced multiple times - actually I use a global value in my case but I hard coded it here for easier reference). URI段(在我的情况下为段3)将直接告诉您的控制器要使用的OFFSET,并且您指定的per_page转换为LIMIT(在我的情况下,我使用$ itemsPerPage进行存储,因为它多次被引用-实际上,我在我的情况下使用的是全局值,但我在此处对其进行了硬编码,以便于参考。

Note you will also need a count method. 请注意,您还需要一个count方法。 You COULD just use your same query, load ALL results, and count it in the controller, but I like to use a separate count method that only generates a minimal query using my WHERE restrictions and selecting just COUNT('id'), which speeds it up considerably. 您可以只使用相同的查询,加载所有结果,然后在控制器中对它进行计数,但是我想使用单独的计数方法,该方法仅使用WHERE限制并仅选择COUNT('id')即可生成最小查询它大大增加了。 (the downside of course is it's an anti-pattern to DRY since the same query code must be defined twice, once for your count method and once for the data querying method) (当然,缺点是它对DRY不利,因为必须将相同的查询代码定义两次,一次用于您的count方法,一次用于数据查询方法)

NOTE ON YOUR CODE 请注意您的代码

Instead of specifying those or_where statements in the controller, I would put them in the model, under a method that describes your search. 与其在控制器中指定这些or_where语句,不如将它们放在描述您的搜索的方法下的模型中。 This sort of search logic should definitely be in the model - the controller should only be accepting the routing, passing the inputs to the model, and then setting up the pagination and view with the results. 这种搜索逻辑肯定应该在模型中-控制器应该只接受路由,将输入传递给模型,然后设置分页并查看结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM