【问题标题】:How to implement search and pagination in CodeIgniter 2.1's database API?如何在 CodeIgniter 2.1 的数据库 API 中实现搜索和分页?
【发布时间】:2013-05-29 19:08:39
【问题描述】:

我在使用 Codeigniter 2.1 构建的网站上遇到了搜索功能问题。具体来说,我在分页和限制为每页 15 个项目时遇到问题。

我的控制器:

              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();
    }
}

然后在我的模型中我有:

            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;
}

如何根据此代码使分页工作?我真的不想更改已经存在的代码,因为搜索工作正常。我只需要它在每页显示 15 条记录,无论搜索什么字词。

【问题讨论】:

    标签: php mysql codeigniter


    【解决方案1】:

    让我们看看我能不能帮你解决问题:

    1. 您的搜索查询需要一个 LIMIT(您已将其注释掉...而且它缺少偏移量...)。
    2. 您需要将您的 POST 页面参数 ($this->input->post('page')) 传递给您的搜索模型,这样您就知道您在哪个页面上,以便计算搜索模型查询的 LIMIT 部分。假设您在模型中将其称为 $current_page
    3. 为什么您的 count_all_results 查询不匹配您的搜索模型的查询?它们应该与相同的 WHERE 条件匹配(除了计数查询没有您要添加到搜索模型查询的 LIMIT )。
    4. 计算 LIMIT(限制和偏移):
      1. $limit = 15;
      2. $offset = $limit * $current_page - $limit;
      3. if($offset
    5. 现在您的限制是:$this->db->limit($offset, $limit); 用于搜索模型的查询。

    希望有帮助!

    【讨论】:

    • 嗨,大卫,谢谢你,我看看能不能让它发挥作用,也许我会再次重写代码,可能会更容易!
    【解决方案2】:

    将您的 per_page 和 num_links 传递到 search() 以计算查询的 LIMIT 和 OFFSET

    您需要做一些简单的数学运算来计算偏移量

    【讨论】:

    • 你的意思是什么?不确定我是否理解
    【解决方案3】:

    正如 David Graham 所说,您缺少 LIMIT 和 OFFSET。 CodeIgniter 分页非常基础,因为底层的“ActiveRecord”本身非常基础(本质上是一个查询构建器,而不是 ORM)。

    因此,您需要考虑 SQL 级别,如何获得所需结果的“页面”。

    下面是我的一个项目的示例代码。

    控制器:

        // 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
    

    型号:

    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;
        }
    }
    

    请注意,我的查询方法具有可选参数 $startIndex 和 $limit。这些是分页工作所必需的。 URI 段(在我的情况下,段 3)将直接告诉您的控制器要使用什么 OFFSET,并且您指定的 per_page 转换为 LIMIT(在我的情况下,我使用 $itemsPerPage 来存储它,因为它被引用多个次 - 实际上我在我的案例中使用了一个全局值,但我在这里对其进行了硬编码以便于参考)。

    请注意,您还需要一个计数方法。您可以只使用相同的查询,加载所有结果,并在控制器中对其进行计数,但我喜欢使用单独的计数方法,该方法仅使用我的 WHERE 限制生成最小查询并仅选择 COUNT('id'),这样可以加快速度它大大增加。 (当然缺点是它是 DRY 的反模式,因为相同的查询代码必须定义两次,一次用于您的计数方法,一次用于数据查询方法)

    代码注释

    我不会在控制器中指定那些 or_where 语句,而是将它们放在模型中,在描述您的搜索的方法下。这种搜索逻辑绝对应该在模型中——控制器应该只接受路由,将输入传递给模型,然后设置分页并查看结果。

    【讨论】:

      猜你喜欢
      • 2018-05-20
      • 1970-01-01
      • 1970-01-01
      • 2019-02-19
      • 2012-12-03
      • 1970-01-01
      • 2010-11-08
      • 2013-02-09
      • 1970-01-01
      相关资源
      最近更新 更多