2008年4月1日 星期二

php分頁function

前一陣子在逛逛yahoo的知識+的時候發現還不少人在問分頁的問題,我就來分享一下自己寫的分頁function吧

function Pager($pager_options = [])
{
    //因為無法使用可變變數取得$_開頭的超級全域變數,所以先利用參考的方式值到自定義的變數
    $post = &$_POST;
    $get = &$_GET;
    $request = &$_REQUEST;

    if (empty($pager_options['totalItems'])) {
        die('未設置 totalItems');
    }

    //取得分頁變數的方式可為request、get、post
    $method = (empty($pager_options['method'])) ? 'request' : $pager_options['method'];
    $method = strtolower($method);
    $method = $$method;

    //取得分頁變數,例如pageVar為pageID,$method為post則分頁的變數則為$_POST['pageID']
    $pageVar = (empty($pager_options['pageVar'])) ? 'pageID' : $pager_options['pageVar'];
    //設定每頁幾筆
    $pager_options['perPage'] = (empty($pager_options['perPage'])) ? 10 : $pager_options['perPage'];
    //顯示同一個頁面顯示幾頁
    $pager_options['delta'] = (empty($pager_options['delta'])) ? 10 : $pager_options['delta'];
    //取得當前頁數
    $pager_options['current'] = (empty($method[$pageVar])) ? 1 : $method[$pageVar];
    //設定link的前置網址
    $pager_options['link'] = (empty($pager_options['link'])) ? $_SERVER['PHP_SELF'] : $pager_options['link'];
    //取得總筆數

    $total = ceil($pager_options['totalItems'] / $pager_options['perPage']);

    if ($pager_options['current'] > $total && $total != 0) {
        $pager_options['current'] = $total;
    }

    $pager_options['page_numbers'] = [
        'current' => $pager_options['current'],
        'total' => $total,
    ];

    $pager_options['deltaStart'] = floor(($pager_options['page_numbers']['current'] - 1) / $pager_options['delta']) * $pager_options['delta'] + 1;
    $pager_options['start'] = ($pager_options['current'] - 1) * $pager_options['perPage'];
    $pager_options['offset'] = $pager_options['perPage'];
    $pager_options['from'] = $pager_options['start'] + 1;
    $pager_options['to'] = $pager_options['from'] + $pager_options['perPage'] - 1;

    return $pager_options;
}

//改利用Pager做查詢會幫你完成分頁
//可用參數
/*
perPage  每頁幾筆
delta  顯示頁數
link  a標籤上的連結
pageVar  分頁的參數
method  取得頁數變數的方法可以為post,get,request
totalItems 總筆數
*/

$page = Pager([
    'perPage' => 10,
    'delta' => 10,
    'link' => 'index.php?op=default',
    'pageVar' => 'page',
    'totalItems' => 100,
]);

var_dump($page);
//回傳的參數
/*
$page['perPage']; 每頁幾筆
$page['delta']; 顯示頁數
$page['link']; a標籤上的連結
$page['totalItems']; 總筆數
$page['page_numbers']['current']; 目前所在頁數
$page['page_numbers']['total']; 總頁數
$page['deltaStart'];     
$page['start']; mysql limit的start值
$page['offset']; mysql limit的offset值
$page['from'];
$page['to'];
*/

原則上這個分頁是我從之前寫的程式抽出來的,原本是和phplib的db物件做結合,當然了,也可以拿去和其他的DB物件做結合,看大家怎麼變化囉

//載入phplib的db物件
require_once dirname(__FILE__).'/../phplib/db_mysql.inc';

//為db物件增加method並增加修改語系問題
class MySQL extends DB_MySQL
{
    /* public: connection parameters */
    public $Host = DBLOCATION;
    public $Database = DBNAME;
    public $User = DBUSER;
    public $Password = DBPW;

    public function query($sql)
    {
        //在每次查詢時先送出定義mysql語系的語法,如果是mysql4.0以下的話請把這一段拿掉
        parent::query('set names utf8');

        return parent::query($sql);
    }
    //取得總筆數
    public function getTotalItems($sql)
    {
        //正規表示將select語法改為 select count(*) from table
        $countSql = preg_replace('/(ORDER|LIMIT)(.*)/i', '', $sql);
        $count_pattern = '/SELECT\s(.*)\sfrom\s/imsU';
        if (preg_match($count_pattern, $countSql, $matched)) {
            $groupby_pattern = '/(GROUP\s?BY(.*))/ism';
            if (preg_match($groupby_pattern, $countSql, $matched2)) {
                $countSql = str_replace($matched2[1], '', $countSql);
                $countSql = str_replace($matched[1], sprintf('COUNT(DISTINCT %s) as totalItems', $matched2[2]), $countSql);
            } else {
                $countSql = str_replace($matched[1], 'COUNT(*) as totalItems', $sql);
            }
            $this->query($countSql);
            $this->next_record();

            return $this->Record['totalItems'];
        } else {
            return 0;
        }
    }

    /*
     * 新增取得分頁的方法
     * 原本在phplib時是使用$db->query($sql);
     * 查詢成功則會回傳true,失敗則回傳false
     * 如果要分頁的話就利用
     * 原本在phplib時是使用$db->Pager($sql);
     * 查詢成功則會回傳分頁資訊,失敗則回傳false
    */
    public function Pager($sql, $pager_options = [])
    {
        //因為無法使用可變變數取得$_開頭的超級全域變數,所以先利用參考的方式值到自定義的變
        $post = &$_POST;
        $get = &$_GET;
        $request = &$_REQUEST;

        //取得分頁變數的方式可為request、get、post
        $method = (empty($pager_options['method'])) ? 'request' : $pager_options['method'];
        $method = strtolower($method);
        $method = $$method;

        //取得分頁變數,例如pageVar為pageID,$method為post則分頁的變數則為$_POST['pageID']
        $pageVar = (empty($pager_options['pageVar'])) ? 'pageID' : $pager_options['pageVar'];
        //設定每頁幾筆
        $pager_options['perPage'] = (empty($pager_options['perPage'])) ? 10 : $pager_options['perPage'];
        //顯示同一個頁面顯示幾頁
        $pager_options['delta'] = (empty($pager_options['delta'])) ? 10 : $pager_options['delta'];
        //取得當前頁數
        $pager_options['current'] = (empty($method[$pageVar])) ? 1 : $method[$pageVar];
        //設定link的前置網址
        $pager_options['link'] = (empty($pager_options['link'])) ? $_SERVER['PHP_SELF'] : $pager_options['link'];
        //取得總筆數
        $pager_options['totalItems'] = (empty($pager_options['totalItems'])) ? $this->getTotalItems($sql) : $pager_options['totalItems'];

        $total = ceil($pager_options['totalItems'] / $pager_options['perPage']);

        if ($pager_options['current'] < 1) {
            $pager_options['current'] = 1;
        } elseif ($pager_options['current'] > $total && $pager_options['current'] != 1) {
            $pager_options['current'] = $total;
        }

        $pager_options['page_numbers'] = [
            'current' => $pager_options['current'],
            'total'   => $total,
        ];

        $pager_options['deltaStart'] = floor(($pager_options['page_numbers']['current'] - 1) / $pager_options['delta']) * $pager_options['delta'] + 1;

        $pager_options['start'] = ($pager_options['current'] - 1) * $pager_options['perPage'];
        $pager_options['offset'] = $pager_options['perPage'];
        $pager_options['from'] = $pager_options['start'] + 1;
        $pager_options['to'] = $pager_options['from'] + $pager_options['perPage'] - 1;
        $limitSql = sprintf('%s LIMIT %s , %s', $sql, $pager_options['start'], $pager_options['offset']);
        if ($this->query($limitSql)) {
            return $pager_options;
        } else {
            return false;
        }
    }
}

//再次繼承
class DB extends MySQL
{
    public $Host = 'localhost';
    public $Database = 'test';
    public $User = 'root';
    public $Password = '';
}

使用方法

$db = new DB;
$sql = 'SELECT * FROM account ORDER BY account';
$results = [];
$page = $db->Pager($sql, [
    'perPage' => 10,
    'delta' => 10,
    'link' => 'index.php?op=default',
    'pageVar' => 'page',
]);

if ($page) {
    while ($db->next_record()) {
        $results[] = $db->Record;
    }
}
print_r($page);
print_r($result);