首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

CodeIgniter 實現 GET 分頁完整實作:搜尋條件保持、分頁配置、資料庫查詢優化

     編輯:PHP 相關知識

CodeIgniter 實現 GET 分頁完整實作

CodeIgniter 內建分頁類庫預設使用 URI 片段(/page/2),但實際專案常需搭配 GET 參數(?page=2&keyword=xxx)以保持搜尋條件。本文提供完整的 GET 分頁實作方案,涵蓋搜尋條件合併、分頁配置、資料庫條件動態構建、關聯查詢與角色權限控制。

控制器完整實作

<?php
class Project extends CI_Controller {

    public function project_search() {
        // 1. 載入類庫與模型
        $this->load->library('pagination');
        $this->load->model('depart_mdl');
        $this->load->model('user_mdl');
        $this->load->model('manage_info_mdl');

        // 2. 獲取所有 GET 參數(搜尋條件 + 分頁)
        $get_data = $this->input->get(); // 自動過濾 XSS

        // 3. 提取搜尋條件變數(便於構建後綴 URL)
        $name           = $get_data['name'] ?? '';
        $username       = $get_data['username'] ?? '';
        $budget         = $get_data['budget'] ?? '';
        $type           = $get_data['type'] ?? '';
        $posttime_start = $get_data['posttime_start'] ?? '';
        $posttime_end   = $get_data['posttime_end'] ?? '';
        $purchase_type  = $get_data['purchase_type'] ?? '';
        $depart_code    = $get_data['depart_code'] ?? '';
        $project_status = $get_data['project_status'] ?? '';
        $bidder_way     = $get_data['bidder_way'] ?? '';

        // 4. 構建分頁 base_url 後綴(保持所有搜尋條件)
        $suffix = http_build_query([
            'name'            => $name,
            'username'        => $username,
            'budget'          => $budget,
            'type'            => $type,
            'posttime_start'  => $posttime_start,
            'posttime_end'    => $posttime_end,
            'purchase_type'   => $purchase_type,
            'depart_code'     => $depart_code,
            'project_status'  => $project_status,
            'bidder_way'      => $bidder_way,
        ]);
        $config['base_url'] = site_url('project/project_search') . '?' . $suffix;

        // 5. 分頁核心配置
        $config['total_rows'] = $this->db->count_all($this->db->dbprefix('project')); // 初始總數,後續會被 where 覆蓋
        $config['per_page'] = 10;
        $config['page_query_string'] = TRUE;      // ✅ 關鍵:啟用 GET 模式
        $config['query_string_segment'] = 'page'; // 參數名:?page=2
        $config['uri_segment'] = 3;               // 相容性保留
        
        // 樣式配置(Bootstrap 4/5)
        $config['full_tag_open'] = '<nav><ul class="pagination">';
        $config['full_tag_close'] = '</ul></nav>';
        $config['num_tag_open'] = '<li class="page-item">';
        $config['num_tag_close'] = '</li>';
        $config['cur_tag_open'] = '<li class="page-item active"><span class="page-link">';
        $config['cur_tag_close'] = '</span></li>';
        $config['next_tag_open'] = '<li class="page-item">';
        $config['next_tag_close'] = '</li>';
        $config['prev_tag_open'] = '<li class="page-item">';
        $config['prev_tag_close'] = '</li>';
        $config['first_tag_open'] = '<li class="page-item">';
        $config['first_tag_close'] = '</li>';
        $config['last_tag_open'] = '<li class="page-item">';
        $config['last_tag_close'] = '</li>';
        $config['attributes'] = ['class' => 'page-link'];
        
        $this->pagination->initialize($config);

        // 6. 獲取當前用戶角色(權限控制)
        $salary_no = $this->session->userdata('salary_no');
        $user = $this->user_mdl->get_user_by_salary_no($salary_no);

        // 7. 構建查詢(動態 WHERE)
        $this->db->from('ustc_project');
        $this->db->join('ustc_admins', 'ustc_admins.salary_no = ustc_project.salary_no');

        // 權限過濾:非超管只能看自己部門或自己的專案
        if ($user->role != 1) {
            $depart_codes = explode(',', $user->grant_depart_code);
            $this->db->where_in('grant_depart_code', $depart_codes);
            $this->db->or_where('ustc_project.salary_no', $salary_no);
        }

        // 搜尋條件動態加入
        if ($name)           $this->db->like('name', $name);
        if ($username)       $this->db->like('username', $username);
        if ($budget)         $this->db->like('budget', $budget);
        if ($type)           $this->db->where('type', $type);
        if ($depart_code)    $this->db->where('depart_code', $depart_code);
        if ($purchase_type)  $this->db->where('purchase_type', $purchase_type);
        if ($project_status) $this->db->where('project_status', $project_status);
        if ($bidder_way)     $this->db->where('bidder_way', $bidder_way);

        // 時間範圍
        if ($posttime_start) $this->db->where('posttime >=', strtotime($posttime_start));
        if ($posttime_end)   $this->db->where('posttime <=', strtotime($posttime_end) + 86399); // 當天結束

        // 8. 計算總數(必須在 limit 之前,且條件相同)
        // 為避免重複構建,可 clone 查詢或重新構建
        // 這裡簡化:重新執行相同 where 獲取總數
        $total_rows = $this->db->count_all_results('ustc_project', false); // false 不重置查詢
        $config['total_rows'] = $total_rows;
        $this->pagination->initialize($config); // 重新初始化更新總數

        // 9. 分頁偏移量
        $page = $get_data['page'] ?? 0;
        $offset = (int)$page;

        // 10. 執行查詢
        $this->db->order_by('posttime', 'DESC');
        $projects = $this->db->limit($config['per_page'], $offset)->get()->result_array();

        // 11. 資料後處理(關聯查詢轉換)
        foreach ($projects as &$p) {
            $p['type']          = $this->manage_info_mdl->get_value_by_id($p['type'])->value;
            $p['purchase_type'] = $this->manage_info_mdl->get_value_by_id($p['purchase_type'])->value;
            $p['depart']        = $this->depart_mdl->get_depart_by_code($p['depart_code'])->name;
        }

        // 12. 視圖資料
        $data['projects'] = $projects;
        $data['user_role'] = $user->role;
        $data['pagination'] = $this->pagination->create_links(); // 生成分頁 HTML

        $this->load->view('project_search', $data);
    }
}
?>

關鍵配置詳解

配置項值說明
page_query_stringTRUE啟用 GET 參數模式(預設 FALSE 為 URI 片段)
query_string_segment'page'頁碼參數名,URL 為 ?page=2
base_url含查詢字串必須包含所有搜尋條件,否則翻頁會丟失篩選
total_rows動態計算需在所有 WHERE 條件加入後計算,否則分頁數錯誤
per_page10每頁筆數

視圖檔範例

<!-- project_search.php -->
<div class="card">
    <div class="card-header">專案列表</div>
    <div class="card-body">
        <table class="table table-striped">
            <thead>
                <tr>
                    <th>名稱</th><th>預算</th><th>類型</th><th>狀態</th><th>發布時間</th><th>操作</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($projects as $p): ?>
                <tr>
                    <td><?= htmlspecialchars($p['name']) ?></td>
                    <td><?= $p['budget'] ?></td>
                    <td><?= $p['type'] ?></td>
                    <td><?= $p['project_status'] ?></td>
                    <td><?= date('Y-m-d', $p['posttime']) ?></td>
                    <td><a href="<?= site_url('project/detail/'.$p['id']) ?>" class="btn btn-sm btn-primary">詳情</a></td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
        
        <!-- 分頁導航 -->
        <div class="d-flex justify-content-center mt-3">
            <?= $pagination ?>
        </div>
    </div>
</div>

常見坑點與解決

問題原因解決
翻頁後搜尋條件消失base_url 未包含查詢字串用 http_build_query 合併所有 GET 參數到 base_url
總筆數不準/分頁數錯誤count_all_results 在 limit 之後調用在 limit 前計算總數,或用 clone 查詢對象
page=0 顯示第一頁offset 計算邏輯CI GET 模式 page 參數直接作為 offset(0-based)
分頁連結指向錯誤 URLsite_url() 未包含 index.php確認 config.php $config['index_page'] 設定正確
中文搜尋條件 URL 亂碼瀏覽器編碼不一致確保專案 charset=UTF-8,http_build_query 自動 urlencode

進階優化建議

  • 查詢複用: 將 WHERE 條件構建封裝為私有方法 _build_search_query(),同時供總數查詢與列表查詢調用,避免重複代碼。
  • 索引優化: 常用搜尋欄位(name、username、posttime、depart_code、project_status)建立複合索引。
  • 快取總數: 搜尋條件不變時,總數可快取 1-5 分鐘(Redis Key: search_count:{md5(serialize($conditions))})。
  • 大資料集游標分頁: 超過 10 萬筆建議改用 ID 游標分頁(WHERE id > $last_id LIMIT 10),避免 OFFSET 深分頁效能問題。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved