基于mysql的分页程序完全解决方案(含普通分页/分段分页/原始分页/微博的since_id类分页)
Author: selfimpr
Blog: http://blog.csdn.net/lgg201
Mail: lgg860911@yahoo.com.cn
Copyright: 转载请注明出处
0. 下载:
本程序可自由修改, 自由分发, 可在http://download.csdn.net/user/lgg201下载test_page.php分页测试
下面是源代码:
page.lib.php
<?php/* * 分页程序 分页测试 * author: selfimpr * blog: http://blog.csdn.net/lgg201 * mail: lgg860911@yahoo.com.cn */require dirname(__FILE__) . '/test_base.php';#初始化数据量define('FEED_ID_MIN',1000);define('FEED_COUNT',972);define('COMMENT_ID_MIN',1000);define('COMMENT_MAX_COUNT',10);define('HOT_MIN',1);define('HOT_MAX',100);define('TRANSPOND_COUNT_MAX',100);#数据库信息$db_host= '127.0.0.1';$db_port= '3306';$db_user= 'paginate_test';$db_pass= 'paginate_test';$db_db= 'paginate_test';$db_charset= 'UTF-8';#全局数据变量名define('ALL_DATAS','_all_datas');#涉及到的keydefine('K_HC_FEEDS','_hc_feed');define('K_TC_FEEDS','_tc_feed');define('K_CC_FEEDS','_cc_feed');define('K_FEED_ID','feed_id');#转发比较函数function comp_transpond_count($a, $b) {$tc= $b['transpond_count'] - $a['transpond_count'];$ic= $b['feed_id'] - $a['feed_id'];return $tc != 0 ? $tc : $ic;}#评论比较函数function comp_comment_count($a, $b) {$cc= $b['comment_count'] - $a['comment_count'];$ic= $b['feed_id'] - $a['feed_id'];return $cc != 0 ? $cc : $ic;}#热点比较函数function comp_hot($a, $b) {$hc= $b['hot'] - $a['hot'];$ic= $b['feed_id'] - $a['feed_id'];return $hc != 0 ? $hc : $ic;}#数据库初始化临时文件$tmp_file= '/tmp/__paginate_test_tmp.sql';#数据库创建脚本$db_init= <<<docDROP DATABASE IF EXISTS `paginate_test`;CREATE DATABASE IF NOT EXISTS `paginate_test`;USE `paginate_test`;DROP TABLE IF EXISTS `feed`;CREATE TABLE IF NOT EXISTS `feed` (`feed_id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '微博ID', `ctime` INT NOT NULL COMMENT '微博创建时间', `content` CHAR(100) NOT NULL DEFAULT '' COMMENT '微博内容', `transpond_count` INT NOT NULL DEFAULT 0 COMMENT '微博转发数') COMMENT '微博表';DROP TABLE IF EXISTS `comment`;CREATE TABLE IF NOT EXISTS `comment` (`comment_id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '评论ID', `content` CHAR(100) NOT NULL DEFAULT '' COMMENT '评论内容', `feed_id` INT NOT NULL COMMENT '被评论微博ID') COMMENT '评论表';DROP TABLE IF EXISTS `hot`;CREATE TABLE IF NOT EXISTS `hot` (`feed_id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '微博ID', `hot` INT NOT NULL DEFAULT 0 COMMENT '微博热度') COMMENT '热点微博表';doc;#初始化数据库function init_db() {global $db_host, $db_port, $db_user, $db_pass, $db_db, $db_init, $tmp_file;$datas= generate_data();file_put_contents($tmp_file, $db_init . chr(10) . data_to_sql($datas));`mysql -u$db_user -p$db_pass -h$db_host -P$db_port $db_db -e 'SOURCE $tmp_file' && rm $tmp_file`;$tc_datas= $datas;$cc_datas= $datas;$hc_datas= $datas;foreach ( $cc_datas as $k => $v ) if ( count($v['comments']) <= 0 ) unset($cc_datas[$k]);usort($tc_datas, 'comp_transpond_count');usort($cc_datas, 'comp_comment_count');usort($hc_datas, 'comp_hot');$GLOBALS[ALL_DATAS]= array(K_TC_FEEDS=> $tc_datas, K_CC_FEEDS=> $cc_datas, K_HC_FEEDS=> $hc_datas, );}#生成测试数据function generate_data() {$i= -1;$j= 0;$feeds= array();while ( ++ $i < FEED_COUNT ) {$feed_id= FEED_ID_MIN + $i;$ctime= time();$transpond_count= rand(0, TRANSPOND_COUNT_MAX);$hot= rand(HOT_MIN, HOT_MAX);$comments= array();$comment_count= rand(0, COMMENT_MAX_COUNT);$k= -1;while ( ++ $k < $comment_count ) {$comment_id= COMMENT_ID_MIN + $j ++;$comments[]= array('content'=> sprintf('cid: %d, fid: %d, ccnt: %d, tcnt: %d, hot: %d', $comment_id, $feed_id, $comment_count, $transpond_count, $hot), 'comment_id'=> $comment_id, );}$feeds[]= array('feed_id'=> $feed_id, 'content'=> sprintf('fid: %d, ccnt: %d, tcnt: %d, hot: %d', $feed_id, $comment_count, $transpond_count, $hot), 'comments'=> $comments, 'comment_count'=> $comment_count, 'transpond_count'=> $transpond_count, 'hot'=> $hot, 'ctime'=> $ctime, );}return $feeds;}#将生成的测试数据转换为sql语句function data_to_sql($feeds) {$feed_sql= 'INSERT INTO feed(feed_id, ctime, content, transpond_count) VALUES ';$comment_sql= 'INSERT INTO comment(comment_id, content, feed_id) VALUES ';$hot_sql= 'INSERT INTO hot(feed_id, hot) VALUES ';foreach ( $feeds AS $feed ) {$feed_sql.= sprintf('(%d, %d, "%s", %d), ', $feed['feed_id'], $feed['ctime'], $feed['content'], $feed['transpond_count']);if ( !empty($feed['comments']) )foreach ( $feed['comments'] as $comment ) $comment_sql.= sprintf('(%d, "%s", %d), ', $comment['comment_id'], $comment['content'], $feed['feed_id']);$hot_sql.= sprintf('(%d, %d), ', $feed['feed_id'], $feed['hot']);}return substr($feed_sql, 0, strlen($feed_sql) - 2) . ";\n" . substr($comment_sql, 0, strlen($comment_sql) - 2) . ";\n" . substr($hot_sql, 0, strlen($hot_sql) - 2);}#格式化打印测试数据function print_feeds($feeds) {foreach ( $feeds as $feed ) {printf("\tfeed_id: %d, transpond_count: %d, hot: %d, content: '%s'\n", $feed['feed_id'], $feed['transpond_count'], $feed['hot'], $feed['content']);foreach ( $feed['comments'] as $comment ) {printf("\t\tcomment_id: %d, content: '%s'\n", $comment['comment_id'], $comment['content']);}}}#格式化打印所有测试数据function print_all_feeds($all_feeds) {foreach ( $all_feeds as $key => $feeds ) {printf("order type: %s\n", $key);print_feeds($feeds);printf("\n\n");}}#基本断言函数function assert_base($info, $datas, $offset, $count, $file, $line, $sign) {assert_info($file, $line, $sign . ':count');assert(intval($count) === count(p_datas($info)));assert_info($file, $line, $sign . ':datas');if ( is_array(p_datas($info)) )foreach ( p_datas($info) as $data ) assert(intval($data[K_FEED_ID]) == intval($datas[$offset ++][K_FEED_ID]));}#断言热门数据function assert_hot($info, $offset, $count, $file, $line) {assert_base($info, $GLOBALS[ALL_DATAS][K_HC_FEEDS], $offset, $count, $file, $line, __FUNCTION__);}#断言热转数据function assert_transpond($info, $offset, $count, $file, $line) {assert_base($info, $GLOBALS[ALL_DATAS][K_TC_FEEDS], $offset, $count, $file, $line, __FUNCTION__);}#断言热评数据function assert_comment($info, $offset, $count, $file, $line) {assert_base($info, $GLOBALS[ALL_DATAS][K_CC_FEEDS], $offset, $count, $file, $line, __FUNCTION__);}#初始化数据库连接function init_conn() {global $db_host, $db_port, $db_user, $db_pass, $db_db, $db_charset;static $conn;if ( is_null($conn) ) {$conn= mysql_connect($db_host . ':' . $db_port, $db_user, $db_pass);mysql_select_db($db_db, $conn);mysql_set_charset($db_charset, $conn);}return $conn;}#单纯传统分页测试function test_tradition($sql, $assert, $total_record) {$total_page= ceil($total_record / 10);$remain= $total_record % 10 ? $total_record % 10 : 10;$info= mysql_paginate_tradition(init_conn(), $sql, -1, 10);$assert($info, 0, 10, __FILE__, __LINE__);$info= mysql_paginate_tradition(init_conn(), $sql, 1, 10);$assert($info, 0, 10, __FILE__, __LINE__);$info= mysql_paginate_tradition(init_conn(), $sql, 2, 10);$assert($info, 10, 10, __FILE__, __LINE__);$info= mysql_paginate_tradition(init_conn(), $sql, 2, 10);$assert($info, 10, 10, __FILE__, __LINE__);$info= mysql_paginate_tradition(init_conn(), $sql, $total_page - 1, 10);$assert($info, ($total_page - 2) * 10, 10, __FILE__, __LINE__);$info= mysql_paginate_tradition(init_conn(), $sql, $total_page, 10);$assert($info, ($total_page - 1) * 10, $remain, __FILE__, __LINE__);$info= mysql_paginate_tradition(init_conn(), $sql, $total_page + rand(1, 10), 10);$assert($info, ($total_page - 1) * 10, $remain, __FILE__, __LINE__);}#单纯分段分页测试function test_ping($sql, $assert, $total_record) {$total_ping= ceil($total_record / 10);$total_page= ceil($total_ping / 3);$remain= $total_record % 10 ? $total_record % 10 : 10;$remain_ping= $total_ping % 3 ? $total_ping % 3 : 3;$info= mysql_paginate_ping(init_conn(), $sql, -1, -1, 3, 10);$assert($info, 0, 10, __FILE__, __LINE__);$info= mysql_paginate_ping(init_conn(), $sql, -1, 2, 3, 10);$assert($info, 10, 10, __FILE__, __LINE__);$info= mysql_paginate_ping(init_conn(), $sql, 1, 3, 3, 10);$assert($info, 20, 10, __FILE__, __LINE__);$info= mysql_paginate_ping(init_conn(), $sql, 1, 4, 3, 10);$assert($info, 20, 10, __FILE__, __LINE__);$info= mysql_paginate_ping(init_conn(), $sql, 5, 2, 3, 10);$assert($info, 130, 10, __FILE__, __LINE__);$info= mysql_paginate_ping(init_conn(), $sql, $total_page, $remain_ping, 3, 10);$assert($info, ($total_ping - 1) * 10, $remain, __FILE__, __LINE__);$info= mysql_paginate_ping(init_conn(), $sql, $total_page + rand(1, 10), $remain_ping, 3, 10);$assert($info, ($total_ping - 1) * 10, $remain, __FILE__, __LINE__);}#单纯原始分页测试function test_raw($sql, $assert, $total_record) {$remain= $total_record % 10 ? $total_record % 10 : 10;$info= mysql_paginate_raw(init_conn(), $sql, -1, 10);$assert($info, 0, 10, __FILE__, __LINE__);$info= mysql_paginate_raw(init_conn(), $sql, 100, 10);$assert($info, 100, 10, __FILE__, __LINE__);$info= mysql_paginate_raw(init_conn(), $sql, ($total_record - $remain), 10);$assert($info, ($total_record - $remain), $remain, __FILE__, __LINE__);}#单纯since_id分页测试function test_since_id($sql, $assert) {#第一页$info_0= mysql_paginate_since_id(init_conn(), $sql, 10);$assert($info_0, 0, 10, __FILE__, __LINE__);#无数据(第一页之前$info_1= mysql_paginate_since_id(init_conn(), $sql, 10, p_prev_id($info_0));$assert($info_1, 0, 0, __FILE__, __LINE__);#第二页$info_2= mysql_paginate_since_id(init_conn(), $sql, 10, NULL, p_next_id($info_0));$assert($info_2, 10, 10, __FILE__, __LINE__);#第三页$info_3= mysql_paginate_since_id(init_conn(), $sql, 10, NULL, p_next_id($info_2));$assert($info_3, 20, 10, __FILE__, __LINE__);#第四页$info_4= mysql_paginate_since_id(init_conn(), $sql, 10, NULL, p_next_id($info_3));$assert($info_4, 30, 10, __FILE__, __LINE__);#第三页$info_5= mysql_paginate_since_id(init_conn(), $sql, 10, p_prev_id($info_4), NULL);$assert($info_5, 20, 10, __FILE__, __LINE__);#第二页(第二页至第三页之间的前10条)$info_5= mysql_paginate_since_id(init_conn(), $sql, 10, p_next_id($info_0), p_prev_id($info_4));$assert($info_5, 10, 10, __FILE__, __LINE__);}#传统分页复合since_id分页测试function test_tradition_since_id($sql, $assert, $total_record) {$total_page= ceil($total_record / 10);$remain= $total_record % 10 ? $total_record % 10 : 10;$info= mysql_paginate_tradition_since_id(init_conn(), $sql, -1, 10);$assert($info, 0, 10, __FILE__, __LINE__);$info= mysql_paginate_tradition_since_id(init_conn(), $sql, 2, 10);$assert($info, 10, 10, __FILE__, __LINE__);$info= mysql_paginate_tradition_since_id(init_conn(), $sql, $total_page - 1, 10);$assert($info, ($total_page - 2) * 10, 10, __FILE__, __LINE__);$info= mysql_paginate_tradition_since_id(init_conn(), $sql, $total_page, 10);$assert($info, ($total_page - 1) * 10, $remain, __FILE__, __LINE__);#第一页$info_0= mysql_paginate_tradition_since_id(init_conn(), $sql, 1, 10, TRUE, TRUE);$assert($info_0, 0, 10, __FILE__, __LINE__);#无数据(第一页之前)$info_1= mysql_paginate_tradition_since_id(init_conn(), $sql, 1, 10, p_prev_id($info_0));$assert($info_1, 0, 0, __FILE__, __LINE__);#第二页$info_2= mysql_paginate_tradition_since_id(init_conn(), $sql, 1, 10, NULL, p_next_id($info_0));$assert($info_2, 10, 10, __FILE__, __LINE__);#第三页$info_3= mysql_paginate_tradition_since_id(init_conn(), $sql, 1, 10, NULL, p_next_id($info_2));$assert($info_3, 20, 10, __FILE__, __LINE__);#第二页$info_4= mysql_paginate_tradition_since_id(init_conn(), $sql, 1, 10, p_prev_id($info_3));$assert($info_4, 10, 10, __FILE__, __LINE__);#第四页$info_5= mysql_paginate_tradition_since_id(init_conn(), $sql, 1, 10, NULL, p_next_id($info_3));$assert($info_5, 30, 10, __FILE__, __LINE__);#第三页$info_6= mysql_paginate_tradition_since_id(init_conn(), $sql, 2, 10, NULL, p_next_id($info_0));$assert($info_6, 20, 10, __FILE__, __LINE__);#第八页$info_7= mysql_paginate_tradition_since_id(init_conn(), $sql, 7, 10, NULL, p_next_id($info_0));$assert($info_7, 70, 10, __FILE__, __LINE__);#最后一页$info_8= mysql_paginate_tradition_since_id(init_conn(), $sql, $total_page - 1, 10, NULL, p_next_id($info_0));$assert($info_8, ($total_page - 1) * 10, $remain, __FILE__, __LINE__);#(TODO 分段分页/传统分页/原始分页与since_id分页联合使用时, 记录数是since_id条件附加之前的记录数, 因此会导致页码数据错乱, 目前不对此进行处理)#越界访问$info_8= mysql_paginate_tradition_since_id(init_conn(), $sql, $total_page, 10, NULL, p_next_id($info_0));$assert($info_8, 0, 0, __FILE__, __LINE__);}#分段分页复合since_id分页测试function test_ping_since_id($sql, $assert, $total_record) {$total_ping= ceil($total_record / 10);$total_page= ceil($total_ping / 3);$remain= $total_record % 10 ? $total_record % 10 : 10;$remain_ping= $total_ping % 3 ? $total_ping % 3 : 3;$info= mysql_paginate_ping_since_id(init_conn(), $sql, -1, -1, 3, 10);$assert($info, 0, 10, __FILE__, __LINE__);$info= mysql_paginate_ping_since_id(init_conn(), $sql, -1, 2, 3, 10);$assert($info, 10, 10, __FILE__, __LINE__);$info= mysql_paginate_ping_since_id(init_conn(), $sql, 1, 3, 3, 10);$assert($info, 20, 10, __FILE__, __LINE__);$info= mysql_paginate_ping_since_id(init_conn(), $sql, 1, 4, 3, 10);$assert($info, 20, 10, __FILE__, __LINE__);$info= mysql_paginate_ping_since_id(init_conn(), $sql, 5, 2, 3, 10);$assert($info, 130, 10, __FILE__, __LINE__);$info= mysql_paginate_ping_since_id(init_conn(), $sql, $total_page, $remain_ping, 3, 10);$assert($info, ($total_ping - 1) * 10, $remain, __FILE__, __LINE__);$info= mysql_paginate_ping_since_id(init_conn(), $sql, $total_page + rand(1, 10), $remain_ping, 3, 10);$assert($info, ($total_ping - 1) * 10, $remain, __FILE__, __LINE__);#第一页第一段$info_0= mysql_paginate_ping_since_id(init_conn(), $sql, 1, 1, 3, 10, TRUE, TRUE);$assert($info_0, 0, 10, __FILE__, __LINE__);#无数据(第一页之前)$info_1= mysql_paginate_ping_since_id(init_conn(), $sql, 1, 1, 3, 10, p_prev_id($info_0));$assert($info_1, 0, 0, __FILE__, __LINE__);#第一页第二段$info_2= mysql_paginate_ping_since_id(init_conn(), $sql, 1, 1, 3, 10, NULL, p_next_id($info_0));$assert($info_2, 10, 10, __FILE__, __LINE__);#第一页第三段$info_3= mysql_paginate_ping_since_id(init_conn(), $sql, 1, 1, 3, 10, NULL, p_next_id($info_2));$assert($info_3, 20, 10, __FILE__, __LINE__);#第一页第二段$info_4= mysql_paginate_ping_since_id(init_conn(), $sql, 1, 1, 3, 10, p_prev_id($info_3));$assert($info_4, 10, 10, __FILE__, __LINE__);#第一页第一段$info_5= mysql_paginate_ping_since_id(init_conn(), $sql, 1, 1, 3, 10, NULL, p_next_id($info_3));$assert($info_5, 30, 10, __FILE__, __LINE__);#第一页第三段$info_6= mysql_paginate_ping_since_id(init_conn(), $sql, 1, 2, 3, 10, NULL, p_next_id($info_0));$assert($info_6, 20, 10, __FILE__, __LINE__);#第七页第三段$info_7= mysql_paginate_ping_since_id(init_conn(), $sql, 7, 2, 3, 10, NULL, p_next_id($info_0));$assert($info_7, 200, 10, __FILE__, __LINE__);#倒数第二页最后一段$info_9= mysql_paginate_ping_since_id(init_conn(), $sql, $total_page - 1, 2, 3, 10, NULL, p_next_id($info_0));$assert($info_9, ($total_ping - $remain_ping - 1) * 10, 10, __FILE__, __LINE__);#(TODO 分段分页/传统分页/原始分页与since_id分页联合使用时, 记录数是since_id条件附加之前的记录数, 因此会导致页码数据错乱, 目前不对此进行处理)#越界访问$info_10= mysql_paginate_ping_since_id(init_conn(), $sql, $total_page + rand(1, 10), 3, 3, 10, NULL, p_next_id($info_0));$assert($info_10, 0, 0, __FILE__, __LINE__);}#原始分页复合since_id分页测试function test_raw_since_id($sql, $assert, $total_record) {$remain= $total_record % 10 ? $total_record % 10 : 10;$info= mysql_paginate_raw_since_id(init_conn(), $sql, -1, 10);$assert($info, 0, 10, __FILE__, __LINE__);$info= mysql_paginate_raw_since_id(init_conn(), $sql, 100, 10);$assert($info, 100, 10, __FILE__, __LINE__);$info= mysql_paginate_raw_since_id(init_conn(), $sql, $total_record - $remain, 10);$assert($info, $total_record - $remain, $remain, __FILE__, __LINE__);#第一页$info_0= mysql_paginate_raw_since_id(init_conn(), $sql, 0, 10, TRUE, TRUE);$assert($info_0, 0, 10, __FILE__, __LINE__);#无数据(第一页之前)$info_1= mysql_paginate_raw_since_id(init_conn(), $sql, 0, 10, p_prev_id($info_0));$assert($info_1, 0, 0, __FILE__, __LINE__);#第二页$info_2= mysql_paginate_raw_since_id(init_conn(), $sql, 0, 10, NULL, p_next_id($info_0));$assert($info_2, 10, 10, __FILE__, __LINE__);#第三页$info_3= mysql_paginate_raw_since_id(init_conn(), $sql, 0, 10, NULL, p_next_id($info_2));$assert($info_3, 20, 10, __FILE__, __LINE__);#第二页$info_4= mysql_paginate_raw_since_id(init_conn(), $sql, 0, 10, p_prev_id($info_3));$assert($info_4, 10, 10, __FILE__, __LINE__);#第四页$info_5= mysql_paginate_raw_since_id(init_conn(), $sql, 0, 10, NULL, p_next_id($info_3));$assert($info_5, 30, 10, __FILE__, __LINE__);#最后一页$info_6= mysql_paginate_raw_since_id(init_conn(), $sql, $total_record - $remain - 10, 10, NULL, p_next_id($info_0));$assert($info_6, $total_record - $remain, $remain, __FILE__, __LINE__);#(TODO 分段分页/传统分页/原始分页与since_id分页联合使用时, 记录数是since_id条件附加之前的记录数, 因此会导致页码数据错乱, 目前不对此进行处理)#越界访问$info_7= mysql_paginate_raw_since_id(init_conn(), $sql, 970, 10, NULL, p_next_id($info_0));$assert($info_7, 0, 0, __FILE__, __LINE__);}#初始化数据init_db();$h_sql= 'SELECT f.feed_id, f.content, h.hot FROM feed AS f JOIN hot AS h ON f.feed_id = h.feed_id ORDER BY h.hot DESC, f.feed_id DESC';$c_sql= 'SELECT f.feed_id, f.content, COUNT(c.comment_id) AS count FROM feed AS f JOIN comment AS c ON f.feed_id = c.feed_id GROUP BY c.feed_id ORDER BY COUNT(c.comment_id) DESC, f.feed_id DESC';$t_sql= 'SELECT feed_id, content, transpond_count FROM feed ORDER BY transpond_count DESC, feed_id DESC';$data_infos= array(array($c_sql, 'assert_comment', count($GLOBALS[ALL_DATAS][K_CC_FEEDS])), array($h_sql, 'assert_hot', count($GLOBALS[ALL_DATAS][K_HC_FEEDS])), array($t_sql, 'assert_transpond', count($GLOBALS[ALL_DATAS][K_TC_FEEDS])), );$use_cases= array('test_tradition', 'test_ping', 'test_raw', 'test_since_id', 'test_tradition_since_id', 'test_ping_since_id', 'test_raw_since_id', );foreach ( $data_infos as $data_info ) {foreach ( $use_cases as $use_case )call_user_func_array($use_case, $data_info);}