FleaPHP分页方法讲解

本来这篇文章是不想写的,要写早几年就应该写了,为甚么突然想起要写一篇这样的东西呢?无他,因为随着年岁的增长,近日发觉自己的记忆力下降得非常厉害,看过的东西转头即忘。莫非这是老年痴呆的先兆?因此赶紧记之,以作备忘。

开发系统时,FleaPHP的分页大家用得可能比较多了,但都是怎么用的呢?而且使用了多少种分页方法呢?哪种分页方法用的较多呢?日常使用过程中,对FleaPHP中的分页助手的原有功能是否满意呢?一直以来,本人对FleaPHP的分页助手的功能都不满意,灰常有意见。因为这个实在太简单了,简单到分页助手只是为你准备好分页数据,至于分页的显示样式等,则只能靠自己了。本人曾多次向dualface(廖宇雷)教主他老人家提出宝贵意见,但他老人家就是不接受,我有什么办法呢?!看到这里,有些看官自然有话要说,既然对分页助手诸多不满,为什么你自己不开发一个?这个嘛——,当然了,自己搞一个,也不是不行,但本人比较懒,平时只喜欢“拿来主义”,除非没有,逼得自己非去瞎搞不可,否则都是拿来即用。话又要说回来,如果样样都要自己搞一套,岂非老年痴呆得更快?何况已经有了一个分页自定义插件,我觉得大体上可以应付过去了,就不必再另搞一套了,无此必要。

孔老夫子因自己衰老得厉害,已经无法梦见周公了而常常哀叹。我呢,哎,人老了碎话就多,这更是要得老年痴呆的证据了,请看官原谅则个。

话确实多了,扯远了,回到正题。继续谈分页......

本人在进行分页时,下面三种分页样式经常用到,就是:

1、使用分页自定义控件,就是Pagernav插件,显示“<<上页 1 2 3 ...... 下页>>”链接字串;图示效果:


 
2、直接使用分页助手,显示分页索引数字链接字串,如:“1 2 3 4 ...... 8”;图示效果:


 
3、对分页助手进行功能扩展,显示“首页|上页|下页|末页”链接字串;图示效果:


 
是否还有其它分页方法?比如Ajax分页。这个当然可以有,而且是真的有。但由于与本文所述无关,因此忽略不讲。

以上三种分页都需要用到分页助手,因此,我们先复习一下分页助手的构造函数原型。

	/**
     * 构造函数
     *
     * 如果 $source 参数是一个 TableDataGateway 对象,则 FLEA_Helper_Pager 会调用
     * 该 TDG 对象的 findCount() 和 findAll() 来确定记录总数并返回记录集。
     *
     * 如果 $source 参数是一个字符串,则假定为 SQL 语句。这时,FLEA_Helper_Pager
     * 不会自动调用计算各项分页参数。必须通过 setCount() 方法来设置作为分页计算
     * 基础的记录总数。
     *
     * 同时,如果 $source 参数为一个字符串,则不需要 $conditions 和 $sortby 参数。
     * 而且可以通过 setDBO() 方法设置要使用的数据库访问对象。否则 FLEA_Helper_Pager
     * 将尝试获取一个默认的数据库访问对象。
     *
     * @param TableDataGateway|string $source
     * @param int $currentPage
     * @param int $pageSize
     * @param mixed $conditions
     * @param string $sortby
     * @param int $basePageIndex
     *
     * @return FLEA_Helper_Pager
     */
    function FLEA_Helper_Pager(& $source, $currentPage, $pageSize = 20, $conditions = null, $sortby = null, $basePageIndex = 0)

 

参数说明:
$source -- TableDataGateway 对象,也就是数据表对象实例;
$currentPage -- 当前页页码;
$pageSize -- 每页显示记录数,默认为每页显示20条记录;
$conditions -- 分页查询条件参数;
$sortby -- 记录排序参数,默认为null,即按ASC升序排列;
$basePageIndex -- 基本页索引参数,默认为0,即分页时以 0 开始计数,如果设为 1,即分页时以 1 开始计数;这个一直以来争议很大,为什么分页从 0 开始?教主没说。

复习完分页助手的构造函数原型后,继续讲自定义分页插件的使用。

1、分页自定义插件Pagernav的正确使用方法

第一步,下载Pagernav插件,并解压到相关目录下,我习惯放在public/WebControls目录下。
该插件只有两个文件:Pagernav.phppagenav.css 文件。

第二步,在配置文件中指定插件的存放目录。如下所示:

/**
 * WebControls 扩展控件的保存目录
 */
'webControlsExtendsDir'     => __PROJECT_ROOT__ . '/public/WebControls',
 

注意:__PROJECT_ROOT__为单入口文件中所定义的项目根目录,这是一个常量。

第三步,准备模板文件。代码如下面所示:

<link href="public/WebControls/pagenav.css" rel="stylesheet" type="text/css" />

......

<table width="100%" class="table">
  <thead>
	<tr>
      <th width="2%" nowrap="nowrap">选择</th>
      <th width="77%" nowrap="nowrap">标题</th>
      <th width="11%" nowrap="nowrap">时间</th>
      <th width="2%" nowrap="nowrap">状态</th>
      <th width="8%" nowrap="nowrap">操作</th>
    </tr>
  </thead>
  <tbody>
    {{ section name=i loop=$lists }}
    <tr>
      <td><input type="checkbox" name="ids[]" id="ids[]" value="{{ $lists[i].art_id }}" /></td>
      <td nowrap="nowrap">{{ $lists[i].title }}</td>
      <td nowrap="nowrap">{{ $lists[i].created }}</td>
      <td nowrap="nowrap">{{ $lists[i].status }}</td>
      <td nowrap="nowrap">&nbsp;<a href="{{ url controller='Article' action='Edit' id=$lists[i].art_id page=$page }}" title="编辑"><img src="images/24.png" width="16" height="16" align="absmiddle" /></a>&nbsp;<a href="{{ url controller='Article' action='Preview' id=$lists[i].art_id page=$page }}" title="预览" target="_blank"><img src="images/preview.png" width="16" height="16" align="absmiddle" /></a>&nbsp;<a href="{{ url controller='Article' action='Open' id=$lists[i].art_id page=$page }}" title="开放浏览"><img src="images/crm.gif" width="16" height="16" align="absmiddle" /></a>&nbsp;<a href="{{ url controller='Article' action='Delete' id=$lists[i].art_id page=$page }}" title="删除" onclick="return confirm('确定要删除该记录吗?');"><img src="images/12.png" width="16" height="16" align="absmiddle" /></a>&nbsp;</td>
    </tr>
    {{ /section }}
    </tbody>
</table>
<div class="cutpage">{{ webcontrol type="pagernav" name="pagenav" pager=$pagerData controller="Article" action="" }}</div>

......
 

上面的模板代码与分页相关的代码不多,需要注意的是:

page=$page -- 当前页码

{{ webcontrol type="pagernav" name="pagenav" pager=$pagerData controller="Article" action="" }} -- 构造分页链接字串
 

其中参数$pagerData为传入控件的分页参数。
如果要传递复杂的参数给自定义分页控件,如传入一个参数数组,可以将上面的代码修改为:

{{ webcontrol type="pagernav" name="pagenav" pager=$pagerData controller="Article" action="" __arrs=$arrs }}
 

如何构造自定义控件?由于超出本文范围,这里不做讲解。各位看官如有兴趣深入,可以看看下面这篇文章:

《使用 FleaPHP 的 WebControls 机制创建可复用的用户界面组件》(http://qeephp.com/bbs/viewthread.php?tid=1695&extra=page%3D1%26amp%3Bfilter%3Ddigest

教主出品,必属精品,各位同学需要仔细揣摩。

第三步,编写后台PHP代码。代码如下面所示:

$page = (isset($_GET['page']) ? (int)$_GET['page'] : 0;

// 装载Pager助手类
FLEA::loadHelper('Pager');

// 获取Smarty实例句柄
$tpl = & $this->_getView();

$conditions = array(
	array('uid', $this->user['UID'], '='),
);
$tblArt = & FLEA::getSingleton('Table_Articles');
$pager = & new FLEA_Helper_Pager($tblArt, $page, 15, $conditions, 'art_id DESC');
$rows = $pager->findAll();
$pagerData = $pager->getPagerData();

//dump($pagerData);
//exit;

$tpl->assign('lists', $rows);
$tpl->assign('pagerData', $pagerData);
$tpl->assign('page', $page);

$tpl->display('article_list.tpl');
 

同学们可以看看运行程序后,生成的分页数据样式:

dump($pagerData);

Array
(
    [pageSize] => 2
    [totalCount] => 6
    [count] => 6
    [pageCount] => 3
    [firstPage] => 1
    [firstPageNumber] => 1
    [lastPage] => 3
    [lastPageNumber] => 3
    [prevPage] => 2
    [prevPageNumber] => 2
    [nextPage] => 3
    [nextPageNumber] => 3
    [currentPage] => 3
    [currentPageNumber] => 3
    [pagesNumber] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
        )

)
 

看到这里,同学们觉得分页是不是很简单?用教主的口头禅回答:“对,就是如此简单。”

需要说明的是,上面的讲解以FleaPHP 1.7.1524、Smarty基础。下面的讲解也一样。
Smarty的运行环境参数配置,请参看本人缪作:FleaPHP的单入口文件详解》(http://hegz.iteye.com/blog/646632 )
Pagernav分页插件还可以构造几种不同的分页连接串,我就不再深入了,大家回去自己研究。
同学们也可以看看教主的《Digg.com 样式的分页导航条》(http://qeephp.com/bbs/viewthread.php?tid=1299&extra=page%3D1%26amp%3Bfilter%3Ddigest

讲解完Pagernav插件的使用后,接着讲解如何直接使用分页助手进行分页。

2、直接使用分页助手进行分页

讲解之前,大家先看一下《Pager类使用指南》(http://qeephp.com/bbs/viewthread.php?tid=657&highlight=%E6%8F%90%E4%BA%A4%E6%89%8B%E5%86%8C )这篇资料。
请注意其中的getNavbarIndexs()方法的使用,因为下面要用到。
当然了,这篇《指南》发表的较早,可能与FleaPHP 1.7.1524存在较大出入。但不要紧,我们只需要了解并掌握其分页方法即可。所谓“万变不离其宗”是也。

由于直接使用分页助手进行分页,方法就更加简单了。

第一步,准备分页模板。

与分页相关的代码如下面所示:

<a href="{{ url controller=$url.ctl action=$url.act page=$newsPager.firstPageNumber }}" title="首页">|<</a>
{{ section name=page loop=$newsNavbar }}
{{ if $newsNavbar[page].index == $newsPager.currentPage }}
    <b><font color='red'>[{{ $newsNavbar[page].number }}]</font></b>
{{ else }}
    <a href="{{ url controller=$url.ctl action=$url.act page=$newsNavbar[page].index }}">{{ $newsNavbar[page].number }}</a>
{{ /if }}
{{ /section }}
<a href="{{ url controller=$url.ctl action=$url.act page=$newsPager.lastPageNumber }}" title="末页">>|</a>&nbsp;&nbsp;&nbsp;&nbsp;共有 <font color="Red">{{ $newsPager.count }}</font> 条记录,分为 <font color="Red">{{ $newsPager.pageCount }}</font> 页显示,每页 <font color="Red"> {{ $newsPager.pageSize }}</font> 条
 


模板代码似乎有点复杂。

第二步,编写后台PHP代码。代码如下面所示:

$page = (isset($_GET['page']) ? (int)$_GET['page'] : 1;

// 装载Pager助手类
FLEA::loadHelper('Pager');

// 获取Smarty实例句柄
$tpl = & $this->_getView();

$conditions = array(
	array('uid', $this->user['UID'], '='),
);
$tblArt = & FLEA::getSingleton('Table_Articles');
$pager = & new FLEA_Helper_Pager($tblArt, $page, 15, $conditions, 'art_id DESC',1);
$rows = $pager->findAll();

$tpl->assign('lists', $rows);
$tpl->assign('page', $page);
// 构造分页数字字串
$tpl->assign('newsNavbar', $pager->getNavbarIndexs($page, 8));
// 构造分页状态
$tpl->assign('newsPager', $pager->getPagerData());
$tpl->assign('url', array('ctl' => 'Article','act' => null));

$tpl->display('article_list.tpl');
 

注意上面上面的代码:

$page = (isset($_GET['page']) ? (int)$_GET['page'] : 1;
$pager = & new FLEA_Helper_Pager($tblArt, $page, 15, $conditions, 'art_id DESC', 1);
 

已改变为页码由 1 开始算起。

这个比较简单,不再做展开,大家结合《Pager类使用指南》来理解就行。

下面最后讲一下如何对分页助手进行功能扩展。

3、对分页助手进行功能扩展

如果对分页助手的功能不满意,也可以扩展的方式改进。比如,增加构造“首页|上页|下页|末页”链接字串的方法,增加页码输入跳转方法,改造pageJumper页面选择跳转控件方法等。

功能扩展代码如下:

<?php
/**
 * 文 件 名:extPager.php
 * 说    明:分页类功能扩展
 * 作    者:hegz
 * 最后修改:2010/05/22
 *
 * 在项目目录下创建MyClass目录,用来保存扩展类。
 * 使用方法:
 * FLEA::loadClass('MyClass_extPager');
 * $pager = & new MyClass_extPager();
 *
 */

// 装载FLEA_Helper_Pager类库
FLEA::loadClass('FLEA_Helper_Pager');

// 为了方便使用FLEA::laodClass函数来装载扩展类,按照FleaPHP的命名规范来命名扩展类
class MyClass_extPager extends FLEA_Helper_Pager
{
    /**
     * 构造函数
     *
     */
    function MyClass_extPager(& $source, $currentPage, $pageSize = 20,
                               $conditions = null, $sortby = null) {
        // 继承了父类的构造函数
		parent::FLEA_Helper_Pager($source, $currentPage, $pageSize,
                               $conditions, $sortby, $basePageIndex = 1);
    }

    /**
     * 生成一个页面选择跳转控件
     * 跨平台适用,不用额外JavaScript脚本支持
     *
     * @param string $caption
     * @param array $args
     * @return string
     * @sample: $pager->pageJumper('第 %u 页', null, null, array('type' => 'article'))
     * 示例参数说明:
     *     传入的数组参数第一个为控制器名,第二个为动作名,第三个为其它链接参数数组,
     * 方便使用一个控制器控制来进行同一个页面多个信息板块的分页。
	 * $this->basePageIndex = 1 才能正常使用;
     */
     function pageJumper($caption = '%u', $ctl = null, $act = null, $args = null) {
		$out = "<SELECT name='pageJumper' size='1' onchange='window.location=this.value'>\n";
		for ( $i = 1; $i <= $this->pageCount; $i++ ) {
	    	if ($this->currentPage == $i) {
	    		$extra = "selected";
	    	} else {
	    		$extra = "";
	    	}
	    	$link = "http://" . $_SERVER['HTTP_HOST'];
	    	if (isset($args)) {
	    		$args['page'] = $i;
	    	} else {
	    		$args = array('page' => $i);
	    	}
	    	$link .= url($ctl, $act, $args);
            $out .= "<OPTION VALUE='" . $link . "' $extra>";
            $out .= sprintf($caption, $i) . "</OPTION>\n";
        }
        return $out .= "</SELECT>\n";
    }

    /**
     * 获取分页情况
     *
     * @return sring
     */
    function getPageStatus() {
        return "第 " . $this->currentPageNumber . " 页/共 " . $this->lastPageNumber . " 页";
    }

    /**
     * 获取"首页 | 上页 | 下页 | 未页"分页链接字串,
     *
     * @param string $ctl 控制器名
     * @param string $act 动作名
	 * @param array $args 其它参数数组
	 * @sample: $pager->getPageLink(null, null, array('page' => 3, 'block' => 'article'))
	 * 示例参数说明:
     *     传入的数组参数第一个为控制器名,第二个为动作名,第三个为其它链接参数数组,
     * 方便使用一个控制器控制来进行同一页面多个信息板块的分页。
	 * $this->basePageIndex = 1 才能正常使用;
     */
    function getPageLink($ctl = null, $act = null, $args = null)
    {
        if ($this->currentPage > 1) {
        	if (isset($args['page'])) {
				$args['page'] = $this->firstPageNumber;
        	}
	        $link1 = url($ctl, $act, $args);
	        if (isset($args['page'])) {
	        	$args['page'] = $this->prevPageNumber ;
	        }
	        $link2 = url($ctl, $act, $args);
            $out = "<a href=\"" . $link1 . "\">首页</a> | ";
            $out .= "<a href=\"" . $link2 . "\">上页</a>";
        } else {
            $out = "首页 | 上页";
        }

        if ($this->currentPage <= $this->pageCount -1) {
            $out .= " | ";
	        if (isset($args['page'])) {
	        	$args['page'] = $this->nextPageNumber ;
	        }
	        $link1 = url($ctl, $act, $args);
	        if (isset($args['page'])) {
	        	$args['page'] = $this->lastPageNumber;
	        }
	        $link2 = url($ctl, $act, $args);
            $out .= "<a href=\"" . $link1 . "\">下页</a> | ";
            $out .= "<a href=\"" . $link2 . "\">末页</a>";
        } else {
            $out .= " | 下页 | 末页";
        }
        return $out;
    }

    /**
     * 生成分页码输入栏
     *
     * @param string $ctlName  控制器名称
     * @param string $actName  动作名称
     * @param array $args 链接参数数组
     * @return HTML代码
     */
	function pageInput($ctlName = null, $actName = null, $args = null)
	{
		$ui = & FLEA::initWebControls();
		return  '输入跳转页码:' . $ui->control(
			"textbox",
			'page',
			array(
				'size' => '3',
				'value'=> null,
				//'class' => 'input',
				//'onchange' => 'fnOnPageChanged(this.value)',
				'onkeydown' => "if(event.keyCode==13) {window.location='" . url($ctlName, $actName, $args). "&page='+this.value; return false;}"
			),
			true
		);
	}
}
?>
 


下面讲讲其使用方法。

首先,准备好模板文件。其分页相关代码如下所示:

{{ $cutPageStr }}
 

接着编写后台PHP代码。如下面所示:

if (isset($_GET['page'])) {
	$page = (int)$_GET['page'];
} elseif (isset($_POST['page'])) {
	$page = (int)$_POST['page'];
} else {
	$page = 1;
}

// 装载extPager类
FLEA::loadClass('MyClass_extPager');

// 获取Smarty实例句柄
$tpl = & $this->_getView();

$conditions = array(
	array('uid', $this->user['UID'], '='),
);
$tblArt = & FLEA::getSingleton('Table_Articles');
$pager = & new MyClass_extPager($this->_tblArt, $page, 15, $conditions, 'art_id DESC');
$rows = $pager->findAll();
$cutPageStr = $pager->getPageLink('Article', null, array('page' => $page)) . "&nbsp;&nbsp;&nbsp; " . $pager->getPageStatus() . "&nbsp;&nbsp;&nbsp; " .  $pager->pageInput('Article') . " &nbsp;&nbsp;&nbsp;跳转到" . $pager->pageJumper('第 %u 页', 'Article');
$tpl->assign('lists', $rows);

$tpl->assign('cutPageStr', $cutPageStr);

$tpl->display('article_list.tpl');

 

装载extPager扩展类后,就不需要再装入分页助手类。

同时,由于增加了输入页码跳转功能后,代码:

$page = (isset($_GET['page']) ? (int)$_GET['page'] : 1;
 

需要修改为:

if (isset($_GET['page'])) {
	$page = (int)$_GET['page'];
} elseif (isset($_POST['page'])) {
	$page = (int)$_POST['page'];
} else {
	$page = 1;
}

 

以适应发展变化的需要。

结语

讲解上面的几个分页方法占用了我大半天的休息时间。由于篇幅所限,时间精力不允许,可能讲的不够深入。同学们如果要透彻了解其分页精义,看完本文后,可以回去揣摩分析相关源代码。

 

 

论坛贴:http://qeephp.com/bbs/thread-10998-1-1.html

你可能感兴趣的:(PHP,UI,Ajax,css,bbs)