今天进入狗屎皮重构的第四天。有件事要纪念一下:从今天晚间开始,我的虚拟主机上站点:BSpMq.com以及rsywx.net无法正常访问,必须翻墙。我实在不能明白的是,这样一个纯粹是打P扯谈的站点,一个以藏书、温和时事评论的站点怎么会被封?GFW真的是不可理喻了!
进入妓术专题。
今天进入狗屎皮重构的第四天。我主要解决了分页的问题。
Symfony进行分页也非常简单,因为它内置了sfPagination这个类,我们只要传递一些参数,并在模板中加入一些代码就可以了。
在我的开发中,第一个要解决的分页界面是“类别”中的文章。先放最终效果:
具体实现步骤如下:
首先,修改routing.yml文件中关于显示属于某个类别的文章的路径,加入分页参数:
show_category:
url: /category/:slug/:page
class: sfDoctrineRoute
options:
model: G4pCategory
type: object
param:
module: category
action: show
page: 1
为了简便,我给它定义了缺省的页数为1。
然后,修改category/actions/actions.class.php文件中的executeShow函数:
public function executeShow(sfWebRequest $request)
{
$this->category = $this->getRoute()->getObject();
$this->c_slug=$this->category->getName();
$this->pager=new sfDoctrinePager('G4pArticle', sfConfig::get('app_max_articles_on_category'));
$this->pager->setQuery($this->category->getArticlesQuery($this->category->getId()));
$this->pager->setPage($request->getParameter('page', 1));
$this->pager->init();
}
这里的关键是最后四行。我创建了一个sfDoctrinePager对象,传递了它的查询SQL,并设置其要显示的页面(从sfWebRequest,也就是从$_GET中传递进来),然后进行初始化。注意,这里的SQL——严格说是一个查询的对象不是直接来自于之前我常用的G4pCategoryTable.class.php文件,而是来自G4pCategory.class.php文件。这两个文件的区别说实话我也不是很清楚。按照我的认为,前者主要是包含一些直接返回记录集的函数,我们可以把这个文件看成是一个虚拟的表;后者是一些类方法,一般不会包含直接返回记录集的方法,并可以对类的操作如save,get某个字段的方法进行改写。
getArticlesQuery函数具体定义如下:
public function getArticlesQuery($id)
{
$q=Doctrine::getTable('G4pArticle')->createQuery('a')
->leftJoin('a.G4pCategory')
->where('a.G4pCategory.id=?', array($id))
->orderBy('a.published_at desc, id');
return $q;
}
它和我之前定义的一些方法还是比较类似的,唯一的区别是我直接返回一个Query对象,而不是返回记录集(通过$q->execute()得到)。这是因为具体要得到哪些记录必须由pager来确定,而pager是根据当前页面和每页显示的帖子数量来构建对应的SQL语句的。
另外,请注意这个SQL的构成方法。Article表和Category表显然是一对多的关系(“一”在category表这边),所以我用left join来连接category表,我不需要指定on字段,因为这个是由Symfony根据表关系自动生成的。而在where子句中,我用了带参数的SQL构造,这样也可以有效的防止一些恶意的SQL注入攻击。
最后,我们修改category模块的showSuccess.php函数(它其实就是一个模板文件),引入对应的记录集并加以操作,显示必要的导航等等。全部代码如下。为了方便阅读,我直接加了一些注释,如果你要直接使用代码,请将我的注释去除或者以正确的方式插入:
<?php $articles=$pager-?>getResults() //获得当前的记录集 ?>
<div class="pick">
<div class="titlepic"><span class="sectionhead">文章分类:</span><span class="slug"><?php echo $c_slug; ??></span>
<span class="more"><?php echo link_to('...所有文章', 'list_article') ??>
</span>
</div>
<br></br>
<div class="article">
<ul>
<?php foreach ($articles as $a):
$acount=Doctrine_Core::getTable('g4pcomment')-?>getCommentCount($a->id)->c;
?>
<li><?php echo link_to($a-?>title, 'show_article', $a) ?>
<div class="writer">作者:<?php echo link_to($a-?>author, 'show_author', $a) ?> | <?php echo $a-?>published_at ?> | <a echo="" href="<?php" url_for=""><?php echo $acount ??>评</a>
</div>
</li>
<?php endforeach; ??>
</ul>
<hr></hr>
<?php if($pager-?>haveToPaginate()): //判断是否需要分页,如果需要,那么显示导航条 ?>
<a echo="" href="<?php" url_for=""><img alt="第一页" src="/images/first.png" title="第一页"></img></a>
<a echo="" href="<?php" url_for=""><img alt="上一页" src="/images/previous.png" title="上一页"></img></a>
<?php foreach ($pager-?>getLinks() as $page): ?>
<?php if($page==$pager-?>getPage()): ?>
<span class="currentpage"><?php echo $page ??></span>
<?php else: ??>
<a echo="" href="<?php" url_for=""><?php echo $page ??></a>
<?php endif ??>
<?php endforeach ??>
<a echo="" href="<?php" url_for=""><img alt="下一页" src="/images/next.png" title="下一页"></img></a>
<a echo="" href="<?php" url_for=""><img alt="末页" src="/images/last.png" title="末页"></img></a>
<?php endif ??>
<br></br><strong>本类别中共有<?php echo count($pager) ??>篇文章。</strong>
<?php if($pager-?>haveToPaginate()): ?>
当前为第<?php echo $pager-?>getPage()?>页,共<?php echo $pager-?>getLastPage() ?>页。
<?php endif ??>
</div>
</div>
就这么简单直接。 ===== 作为第4天,今天的工作其实还可以延续,因为我可以用相同的、很少的工作量完成其它几个页面的显示。不过这个就让我稍微偷偷懒,用个实际中的几天来完成吧。 本文收录于[go4pro.org]
220322注:此时的Symfony还没有推出后来很流行的Twig模板引擎。
Leave a Reply to five Cancel reply