重构狗屎皮:第四天

  root
  PHP相关
  2011-03-24
  增加更多TAG »
  4,753次

今天进入狗屎皮重构的第四天。有件事要纪念一下:从今天晚间开始,我的虚拟主机上站点:BSpMq.com以及rsywx.net无法正常访问,必须翻墙。我实在不能明白的是,这样一个纯粹是打P扯谈的站点,一个以藏书、温和时事评论的站点怎么会被封?GFW真的是不可理喻了!

进入妓术专题。

今天进入狗屎皮重构的第四天。我主要解决了分页的问题。

Symfony进行分页也非常简单,因为它内置了sfPagination这个类,我们只要传递一些参数,并在模板中加入一些代码就可以了。

在我的开发中,第一个要解决的分页界面是“类别”中的文章。先放最终效果:

category_with_pagination

具体实现步骤如下:

首先,修改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/>
    <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 href="&lt;?php echo url_for('show_article', $a)?&gt;#comment"><?php echo $acount ?>评</a>
                </div>
            </li>
            <?php endforeach; ?>
        </ul>
        <hr/>
        <?php if($pager->haveToPaginate()): //判断是否需要分页,如果需要,那么显示导航条 ?>
        <a href="&lt;?php echo url_for('show_category',$category) ?&gt;/1"><img src="/images/first.png" title="第一页" alt="第一页" /></a>
        <a href="&lt;?php echo url_for('show_category',$category) ?&gt;/&lt;?php echo $pager-&gt;getPreviousPage() ?&gt;"><img src="/images/previous.png" title="上一页" alt="上一页" /></a>
        <?php foreach ($pager->getLinks() as $page): ?>
        <?php if($page==$pager->getPage()): ?>
            <span class="currentpage"><?php echo $page ?></span>
        <?php else: ?>
        <a href="&lt;?php echo url_for('show_category', $category) ?&gt;/&lt;?php echo $page ?&gt;"><?php echo $page ?></a>
        <?php endif ?>
        <?php endforeach ?>
        <a href="&lt;?php echo url_for('show_category',$category) ?&gt;/&lt;?php echo $pager-&gt;getNextPage() ?&gt;"><img src="/images/next.png" title="下一页" alt="下一页" /></a>
        <a href="&lt;?php echo url_for('show_category',$category) ?&gt;/&lt;?php echo $pager-&gt;getLastPage() ?&gt;"><img src="/images/last.png" title="末页" alt="末页" /></a>
        <?php endif ?>
        <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]


除非另有来自Go4Pro.org或原作者的显式声明,本站点所有文章都按照知识共享许可协议知识共享署名-非商业性使用-禁止演绎 3.0 未本地化版本许可协议进行许可。

Go4Pro.org,V3.0,2009-2014。本站点采用SymfonyBootstrapTwig等技术开发。