Bill's profileCBC's BlogPhotosBlogListsMore Tools Help

CBC's Blog

From Make To Create

Bill Chen

Occupation
Location
Interests

Custom HTML

 

PHP翻页原理和实现

PHP翻页原理和实现


为什么要翻页,司空见惯的事情。当检索的数据足够多的时候,可以看一下google搜索下面的翻页需求。其实,一开始,我们并不需要计划多复杂的算法或者封装的函数。只需要理解并应用其原理即可。

举个例子,假设我们需要显示每页10条记录给用户。
1) 设定的翻页超链接为search.php?page=n,其中n = 1, 2, ..., N.
2) 返回的数据估计为100条,如SELECT COUNT(id) FROM table_name返回100的数据。

且看下面的步骤。
注:本例仅用于MySQL。其它DB原理类似。

1. 计算偏移量


// 获取页号及计算偏移量
$nPage = 1;	// 默认值为1
if (isset($_GET['page'])) $nPage = (int)$_GET['page'];
if ($nPage < 1) $nPage = 1;
$nPageSize = 10;
$nOffset = ($nPage - 1) * $nPageSize;
$s_limit = " LIMIT {$nOffset}, {$nPageSize} ";

上述变量解释:
$nPage - 当前页号
$nPageSize - 每页记录数,这里我们设定为10条
$nOffset - 数据库中记录的偏移量,这里满足一个计算公式:偏移量=(当前页号-1) * 每页记录数
$s_limit - 这里为一段MySQL,意思是限制查询出的记录数,限制范围是从偏移量位置开始,向后提取N条记录。如,LIMIT 4,
20指从第4条记录起,向后提取20条记录,即得到的数据行为5 - 25。

2. 检验需求满足性


于是,可以采用上面得到的$s_limit来检索数据。假设查询SQL如下: $sql_select = "SELECT id, user, email FROM t_user WHERE user LIKE '%bill%' " . $s_limit; 这里多嘴两句,比如这时URL传入为search.php?page=3,那么$s_limit = " LIMIT 20, 10 ",整个SQL = "SELECT id, user, email FROM t_user WHERE user LIKE '%bill%' LIMIT 20, 10 "
自然,返回到浏览器中的记录,也就是从21 - 30条记录了,看来满足了我们翻页的需求,如下表:

浏览器上的页号 数据库中的记录索引
1 1-10
2 11-20
3 21-30
... ...
N (N-1) * 10


3. 显示翻页链接


第2步中,显示给用户的记录内容已经满足要求了,接下来就是提供给用户翻页的链接。一般而言,我们需要显示给用户的翻页按钮/链接应该包括:首页,上一页,页码列,下一页,末页。

这里举例实现一个页码列的链接。从HTML代码角度来看,应该如下:
<a href="search.php?page=1">1</a>
<a href="search.php?page=2">2</a>
<a href="search.php?page=3">3</a>
<a href="search.php?page=4">4</a>

自然地,我们需要知道总共的页数应该是多少。那么,请求一次SQL = " SELECT COUNT(id) AS nTotal FROM t_user WHERE user LIKE '%bill%' "来得到总记录数。假设nTotal = 56。我们可以计算得到总页数 = ceil(56/10) = 6。

于是,
$nTotalPage = ceil(56/10);
$html_pages = "";
for ($i = 1; $i <= $nTotalPage; $i ++) {
	$html_pages .= "<a href=\"search.php?page={$i}\">{$i}</a> \n"
}
echo $html_pages;

于是浏览器上即展示6个超连接。

扩展开来,您可以实现首页,上一页,下一页,末页的超链接和显示样式。

另外,您甚至可以写一个函数来封装,比如传入总记录数,每页记录数,以及网页原始链接,如下面的函数头。

function ShowPages($nTotalRecords, $nCurrentPage, $sUrl, $nPageSize)

参数解释:
$nTotalRecords - 总记录数
$nCurrentPage - 当前页号
$sUrl - 页面原始链接
$nPageSize - 每页记录数

序列化和SOA的紧密关系

  知其然,知其所以然。实际上,任何一种SOA的构架,都离不开序列化的工作。

  泛泛而谈,序列化(Serialization)是将对象状态转换为可保持或传输的格式的过程,而其逆过程就被称为反序列化。这两个过程结合起来,可以轻松地交换数据。于是,序列化可以按下述两种方式构建:
  1. 基于二进制的序列化。可以保持数据类型的保真度。例如,通过将对象二进制序列化到剪贴板,可在不同的应用程序之间共享对象。您可以将对象序列化到流、磁盘、内存和网络等等。远程处理使用序列化“通过值”在计算机或应用程序域之间传递对象。
  2. 基于文本流的序列化。只是序列化公共属性和字段,而不保持数据类型保真度。这时,有多个应用之间进行通讯时,必然就会使用共同遵守的通讯协议或者说标准。这样的标准很多,例如,基于XML的Web服务,SOAP的企业级服务,等等。另外还有一些轻量级标准,如JSON,以及国内的PHPRPC。

  有了上述一个概念,我们再谈谈Web服务(Web Service)。基本上,在客户端和服务器之间所做的唯一假设就是接收方可以理解收到的消息。换句话说,客户端和服务器同意一个协定,然后通过在指定的底层传输协议(例如 HTTP)之上生成遵守该协定的消息来进行通信。因此,用任何语言编写、使用任何组件模型并在任何操作系统上运行的程序,都可以访问Web服务。

  像.Net对下述的协议都提供解析方法:
  using System.Runtime.Serialization.Formatters.Binary;
  using System.Runtime.Serialization.Formatters.Soap;
  using System.Runtime.Serialization.Json;
  using System.Xml.Serialization;

  你可以参看PHPRPC作者提供的一份与.NET Framework 3.5中各种序列化方法的效率比较,也促使我写了本文。

SOA and Web Services

  听过SOA已经很多年了,其实,SOA是软件发展必然会出现的一种思想或者说思潮。人要利用机器来帮忙处理问题,必出现对这个方向的思考,进而得出一种设计思想,或者说观念。广义来说,服务,其实就是把事物交给某个对象来处理,这个对象可以是机器,也可以是人,甚至可以是一组群体。而发送服务需求以及获知服务结果,则需要沟通来联系。用正规的IT的话来说,就是consumer和provider之间的通讯。人类之间规定一种共同的语言来达到目的,机器之间则采用协议进行通讯,而人与机器之间也有沟通的需求存在,进而出现专门的翻译者(程序员)。看来,理解抽象概念并不难,难的是具体的细节处理。

  当前,各种处理具体问题的设计和构架方法应运而生(如,火热的J2EE),依我看是为了复杂而复杂,从而把IT炒的门槛高高,无数概念的炒作,让很多人望而却步,让技术员迷失在庞大的文档库中。选择性阅读,则成为节约精力和时间的重点。Anyway,推荐两篇文章可以帮你快速理解抽象概念以及应用的实例。


Problem: How to stop the upload in upload form

Web问题:如何在上传文件的时候停止/取消上传呢?

答案:
{iframe}.src="javascript:false;";
返回的是字符串false。

收藏一篇值得关注的新技术Comet:How to implement COMET with PHP

另,看了一篇值得琢磨的文章:如何变得有思想?
作者建立了一个简单的模型来描述这个问题:事实+前提+逻辑=观点,从中也给了我一些启示。

总的说来,
1. 构建一种合理的模型来分析事务的本质是合理的,在大多数事物的认识中可以达到高成功率,如现在/将来都要炒得火热得专家系统。
2. 尽量地掌握信息是我们可以正确判断事物的根本。
3. 认识事物本质的方法一般被认同的就是两种:归纳和演绎。如模式识别中的监督式分类和非监督式分类。经济学中的统计方法和各种预测模型。
4. 但是,还存在直觉和灵感这些目前人们无法解释和掌握的东西。比如,各种艺术创作的诞生,人们交往中的喜好厌恶……

 
There are no photo albums.