随着数以千计的Symfony爱好者访问askeet网站,在主页上显示的问题就会逐渐变多。为了避免变慢的请求速度,问题列的随意翻阅就成为必须解决的问题。
Symfony为这一目的提供了一个对象:sfPropelPager。他会封装到数据的请求,从而只会查询当前页面所显示的记录。例如,如果一个页面初始化时每页只显示10个问题,则到数据的请求只会限制为10个结果,并且会设置偏移来在页面中进行匹配。
修改question/list动作
在前面的练习中,我们看到了问题模块的显示动作:
复制代码 代码如下:
public function executeList ()
{
$this->questions = QuestionPeer::doSelect(new Criteria());
}
我们将会修改这个动作来向模板传递一个sfPropelPager而不是传递一个数组。同时,我们会依据感兴趣的数量来对问题进行排序:
复制代码 代码如下:
public function executeList ()
{
$pager = new sfPropelPager('Question', 2);
$c = new Criteria();
$c->addDescendingOrderByColumn(QuestionPeer::INTERESTED_USERS);
$pager->setCriteria($c);
$pager->setPage($this->getRequestParameter('page', 1));
$pager->setPeerMethod('doSelectJoinUser');
$pager->init();
$this->question_pager = $pager;
}
sfPropelPager对象的初始化指明了他包含哪个对象类,以及在一个页面中可以放置的对象的最大数目(在这个例子中为2)。->setPage()方法使用一个请求参数来设置当前页面。例如,如果这个页面参数的值为2,sfPropelPager将会返回3到5的结果。页面请求参数的值变为1,则页面默认会返回1到2的结果。我们可以在Symfony一书的页面章节中了解到关于sfPropelPager对象及其方法的更多信息。
使用一个默认参数
将常量放在我们所使用的配置文件中是一个好主意。例如,每页的结果(在这个例子为2)可以由一个在我们自定义的程序配置中的参数来代替。用下面的代码来改变上面的sfPropelPager行:
复制代码 代码如下:
..
$pager = new sfPropelPager('Question', sfConfig::get('app_pager_homepage_max'));
这里的pager关键字是作为名字空间使用的,这也就是为什么在参数名字中出现的原因。我们可以在Symfony一书的配置一节中查看到更多的关于自定义配置与命名自定义参数规则的更多的内容。
修改listSuccess.php模板
在listSuccess.php模板中,将下面的代码行:
复制代码 代码如下:
<?php foreach($questions as $question): ?>
替换为
复制代码 代码如下:
<?php foreach($question_pager->getResults() as $question): ?>
从而页面显示存储在页面中的结果列表。
添加页面浏览
在这个模板中还需要做另外一件事:页面浏览。现在,模板所做的只是显示前两个问题,但是我们应添加到下一个页面的功能,以及回到前一个页面的功能。要完成添加这些功能,我们需要在模板后面添加下面的代码:
复制代码 代码如下:
<div>
<?php if ($question_pager->haveToPaginate()): ?>
<?php echo link_to('«', 'question/list?page=1') ?>
<?php echo link_to('<', 'question/list?page='.$question_pager->getPreviousPage()) ?>
<?php foreach ($question_pager->getLinks() as $page): ?>
<?php echo link_to_unless($page == $question_pager->getPage(), $page, 'question/list?page='.$page) ?>
<?php echo ($page != $question_pager->getCurrentMaxLink()) ? '-' : '' ?>
<?php endforeach; ?>
<?php echo link_to('>', 'question/list?page='.$question_pager->getNextPage()) ?>
<?php echo link_to('»', 'question/list?page='.$question_pager->getLastPage()) ?>
<?php endif; ?>
</div>
这段代码利用了sfPropelPager对象的各种方法,以及->haveToPaginate(),这个函数只有在请求的结果数目超过了页面尺寸时才会返回真;而->getPreviousPage(),->getNextPage(),->getLastPage()都具有明显示的意义;->getLinks()函数提供了一个页面号的数组;而->getCurrentMaxLink()函数返回最后的页面号。