[强推] Zend Framework 留言本实战 -- 显示留言列表
五、显示留言列表
在留言本这个应用中,我们设计以下功能:留言列表(分页)、新增留言、删除(管理员登陆后)。首先我们来看显示留言列表这个功能。
5.1 概括梳理
经过前面的学习,应该对ZF现MVC的套路有了一些了解了,那么要显示留言列表我们的程序涉及到哪些方面,如果通过ZF提高的MVC框架来实现呢?当访问留言本应用时,我们在首页显示留言列表,并在页面最下方显示新增留言的表单。既然时首页,那么我们的控制器就命名为IndexController.php,当然是存放在/application/controllers目录下面了;紧接着是模型层,既然是显示留言,肯定是gb_message表,那么我们把模型层命名为Message.php(与表明相关联,便于识别),存放在/application/models目录下;最后是视图层,那就是我们的模板页面了,模板页面推荐与控制器同名,即index.phtml,存放在/application/views/scripts/index目录下(这里需要在scripts目录下根据控制器名称建立子目录,便于通过ZF无路径调用并更好的管理模板文件)。现在我们来一起梳理下相关的文件和目录:
/application/controllers/IndexController.php 控制器层
/application/models/Message.php 模型层
/application/views/scripts/index 视图层
以下部分当然是编写三个文件的源代码了,我将会把源代码详细列下,并配上详细说明,有问题的可以留言!
5.2 代码及注释
IndexController.php
<?php
//控制器必须继承自Zend_Controller_Action类
class IndexController extends Zend_Controller_Action
{
//初始化函数,相当于PHP5类中的construct函数,会在类初始化时自动调用
function init()
{
//初始化视图层,并获取应用根路径赋值给视图层
$this->initView();
$this->view->baseUrl = $this->_request->getBaseUrl();
//加载模型类,就是数据库操作类,放在init函数中加载的好处是不用在具体的xxxAction函数中分别加载
Zend_Loader::loadClass('Message');
}
//Action方法,负责执行具体的任务
function indexAction()
{
//定义每页显示的记录条数
$psize = 10;
//获取当前页码,如果不为正整数则重新赋值为1
$page = (int)$this->_request->getParam('page'); //注意,这就是ZF中获取get参数的方法,下面会总结
if($page<1){$page = 1;}
//初始化Message类并获取留言分页列表数据。listMessage函数接收两个参数,分别是每页记录数和当前页码
$message = new Message();
$count = $message->countAll();
$list = $message->listMessage($psize, $page);
//生成分页页码链接,为了简化起见,将所有页码一股脑儿显示出来
$pstr = "";
$maxpage = ceil($count/$psize);
for($i=1; $i<=$maxpage; $i++)
{
if ($page==$i)
{
$pstr .= "<b>{$i}</b>";
}
else
{
$pstr .= "<a href='/index/page/{$i}>{$i}</a>";
}
}
//向视图层赋值并输出视图
$this->view->title = "留言本@ZF Powered"; //将页面标题(html中的title标签)赋值给视图层
$this->view->list = $list;
$this->view->page = $pstr;
$this->render(); //输出视图
}
//析构函数,注销不再需要的资源,可选(PHP5会自动回收)
function __destruct()
{
unset($this->view);
}
}
?>
*****************IndexController涉及到的知识点总结*********************
(1)init函数,控制器的初始化函数,相当于类的构造函数,会在初始化是自动调用,因此最好将整个控制器公用的一些资源放在这个函数中,比如一些公用类的加载和初始化、全局的变量等。
(2)Action函数,实际上是一些形如xxxAction的函数,每一个Action函数负责执行一个具体的请求(或者说任务),这个函数名称中的xxx就是由 http://localhost/xxx 中的xxx,不明白的可以看看ZF的URL解析规则,前面有讲到。
(3)ZF获取参数的方法:get参数==$this->_request->getParam('xxx');,post参数==$this->_request->getPost('xxx');,$this当然是指向当前控制器的。
(4)向视图层赋值。如果在init函数中执行了$this->initView();,则直接调用$this->view->变量名=值;就行了。实际上initView()就是建立一个新的视图实例并赋值给控制器的变量view(当然还有其它相关的操作)。
(5)视图输出。如果严格按照ZF推荐的方式进行目录安排和命名,则显示视图只需调用$this->render();,这样ZF会自动在/application/views/scripts/目录下查找和当前控制器名称同名的目录下的和当前action同名的.phtml文件作为模板显示输出。
Message.php
<?php
//模型类,必须继承自Zend_Db_Table
class Message extends Zend_Db_Table
{
//默认情况下,zend_db_table类会将其类名当作数据库中表名,不是则重新定义,详见ZF手册
protected $_name = 'gb_message';
//重构主键,本例中不需使用,ZF默认表的主键为id,如果不是则重新定义,便于Db类的一些便捷操作,详见ZF手册
protected $_primary = 'mess_id';
//构造函数,获取在入口文件中注册的数据库连接对象
function __construct()
{
parent::__construct();
$this->db = Zend_Registry::get('db');
}
//获取数据总量供分页使用,以下用到Db::select对象,详细请参看ZF手册
function countAll()
{
$select = $this->db->select();
$select->from($this->_name, 'mess_id');
$count = count($this->db->fetchAll($select));
if($count)
{
return $count;
}
return 0;
}
//获取分页后数据,注意最好给参数制定默认值
function listMessage($page=1,$count=20)
{
$select = $this->db->select();
//制定表和获取字段列表
$select->from($this->_name,'*');
//制定排序依据
$select->order('mess_addtime DESC');
//分页获取数据并返回
$select->limitPage($page,$count);
return $this->db->fetchAll($select);
}
//删除留言
function delMessage($mess_id)
{
//使用$this->db->quoteInto来生成sql语句防止sql注入
$where = $this->db->quoteInto('mess_id =?',$mess_id);
$this->db->delete($this->_name,$where);
}
}
?>
*****************Message涉及到的知识点总结*********************
(1)ZF框架Db类表名、主键等相关命名规则和操作,比较对,在本教程中就不再赘述,自己去看ZF手册吧,讲的很清楚。
(2)Db::select对象,为我们提高了一种不受数据库约束构建select的sql语句的工具,详见ZF手册9.2。
(3)ZF提高的防sql注入的方法,安全一定要注意,ZF提供了quote方法和quoteInto方法来帮助构造sql语句,详细请看下ZF手册“第 9 章 Zend_Db”。
PS:大家不要嫌我懒,老是说“见ZF手册”,实际上是因为手册上已经讲解的很详细了,在这里就不需要赘述了,而且本教程是实例教程,偏向于实践,条条款款的东西就少写了。
index.phtml
//be continue 今天累了,明天接着写吧
[ 本帖最后由 tomsou 于 2008-4-7 17:29 编辑 ]
搜索更多相关主题的帖子:
留言列表 留言本 Framework 控制器 实战