php因为种种原因起步比较慢,虽然发展比较快,但是众多开源项目使得,从事二次开发的人比研发的要多很多,所以一半以上的传说中的PHPER根本就不知道框架如何使用。
网上也存在了大量的教材,但总起来说,”已经过时N久了“。无论视频啊,教程啊,基本上都不怎么能用,毕竟zend framework的升级也很快,而且和PHP的更新相似的是,很多内容变动还是比较大的,所以按照原来的教程走下去,100%的是不能运行,除非你下载的zend framework的老掉牙的版本。
以后的日子里,我会将一个完整的例子发布出来。当然最低版本是zend framework 1.11
下面是现有的比较新的例子,首先声明,这个例子不是我写的,我并没有运行测试过,但是基本配置都是正确的,思路也是对的。
我们来看一下吧:
使用Zend Framework需要满足下面的条件:
• PHP 5.2.4 或以上版本
• 支持mod_rewrite或类似功能的WEB服务器
本教程以PHP5.2.8或更高版本,Apache Web服务器。而且Apache已安装并正确配置了mod_rewrite扩
展。 (apache 的版本是:2.2.16)
必须保证Apache支持 .htaccess文件, 这通常中通过修改httpd.conf中的
AllowOverride None
为
AllowOverride All
来实现。
1,去官方下载一个zf框架,选择适合你版本,建议不要低于1.8.4.。现在开始创建项目:cmd 运行zf.bat 来创建工程
create module myproject就可以创建一个叫myproject的项目工程。会生成一下目录结构

configs/application.ini,在[production]部分的最后添加下面的代码:
resources.db.params.host = localhost
resources.db.params.username = root
resources.db.params.password = 123456
resources.db.params.dbname = nestable
Zend_Application_Module_Autoloader类用来做这些工作,我们可以在Bootstrap类中使用它。要添加的部分已
经加粗:
表格建立数据接口。对于较复杂的项目,经常需要建一个模型类,这个类以保护(protected)成员变量的方式
使用一个或多个Zend_Db_Table实例。但在这个教程中,我们将创建一个扩展自Zend_Db_Table的模型。
使用数据表名来命名更容易让人理解。因为我们表名为albums,加上前缀后类名将是Model_DbTable_Albums。
为了让Zend_Db_Table知道它要操作的表的名称,我们需要将其保护成员属性$_name设置为数据表名称。另外,
Zend_Db_Table假定表有一个字段名为id自动增加(Auto Increment)的主键,当然根据需要,这个字段名称可以
改变。
的内容:
{
{
$data = array(
‘artist’ => $artist,
‘title’ => $title,
);
$this->update($data, ‘id = ‘. (int)$id);
}
public function deleteAlbum($id)
{
$this->delete(‘id =’ . (int)$id);
}
}
我们创建了四个辅助方法,用来与数据表接口。getAlbum()查询一条记录存放到数组中,addAlbum()向数据库
中增加一条记录,updateAlbum()修改一条唱片记录,deleteAlbum()完全删除一条记录。每个方法的代码都很
容易理解。你也可以为Zend_Db_Table设置关联表获取关联数据,虽然这个教程中不需要这么做。
我们需要使用从模型中获取的数据填充到控制器中,并获取视图脚本来展示这些数据,但在此之前,我们需要
理解Zend Framework的视图系统是如何工作的。
布局和视图(Layouts and Views)
毫不奇怪,Zend Framework的视图组件叫做Zend_View。Zend_View让我们可以将页面和动作函数分离。
Zend_View的基本使用方法如下:
$view = new Zend_View();
$view->setScriptPath(‘/path/to/scripts’);
echo $view->render(‘script.php’);
显然,如果我们直接将这些代码写到每一个动作函数中,就不得不到处无聊地重复这些跟动作关系不大的 “结
构化”代码。我们希望能将视图的初始化代码放在其它的地方,然后在每个动作函数中直接访问已初始化过的
视图对象。Zend Framework为我们提供一个叫做ViewRenderer的视图助手(Action Helper)。它负责为我们初始
化控制器中的view属性($this->view),并在动作调度后显示视图脚本。
显示过程首先通知Zend_View对象在views/scripts/{controller name} 目录中查找显示脚本,然后显示与动作
名称相同,扩展名为.phtml 的显示脚本。即显示的视图文件名为views/scripts/{controller name}/{action
name}.phtml,显示的内容将附加到应答对象(Response Object)的应答内容(body)中。
应答对象将MVC系统生成的HTTP头,应答内容以及所有异常信息整合在一起。前端控制器在调度过程的结尾处自
动将HTTP头以及应答内容返回给用户。
在用zf命令创建项目和添加控制器与动作的时候,这些都已经由Zend_Tool为我们创建好。
公共HTML代码: Layouts
很快你就会发现在我们的视图中有大量相同的HTML代码,至少有用于网页头部或底部的相同代码,还有可能有
一两个相同的侧边栏。由于这个问题非常普遍,因此Zend Framework专门设计了Zend_Layout组件来解决这个问
题。 Zend_Layout组件允许我们将相同的头部和尾部代码移到独立的布局显示脚本(layout view script)中,
并在布局显示脚本中包含与正在执行的动作相关的显示代码。
这些布局文件默认保存在application/layouts/,有一个资源可以被Zend_Application用来配置Zend_Layout。
首先创建application/layouts/文件夹,然后在配置文件configs/applications.ini中的[production]部分最
后添加一行:
resources.layout.layoutpath = APPLICATION_PATH “/layouts”
我们还需要在Bootstrap类中为视图设置全局变量。我们再一次使用_init方法,命名为_initViewHelpers()。编
辑application/Bootstrap.php文件,将下面的代码添加到_initAutoload()方法下面:
application/Bootstrap.php
…
protected function _initViewHelpers()
{
$this->bootstrap(‘layout’);
$layout = $this->getResource(‘layout’);
$view = $layout->getView();
$view->doctype(‘XHTML1_STRICT’);
$view->headMeta()->appendHttpEquiv(‘Content-Type’, ‘text/html;charset=utf-8′);
$view->headTitle()->setSeparator(‘ – ‘);
$view->headTitle(‘Zend Framework Tutorial’);
}
我们使用bootstrap()成员变量确保初始化布局资源(layout resource),然后使用getResource()方法得到
Zend_Layout对象,最后利用getView()方法得到视图。
一旦我们有了$view实例,我们就可以用一些助手函数来准备后面的渲染。doctype()视图助手用来设置我们想
要的DOCTYPE。它对保证其他的视图助手能生成准备的HTML代码来说是非常有用的。我们使用headMeta()来设置
content-type META标签,headTitle()视图助手用来设置title中的分隔符和title最后一部分。
调试的时候,Zend_Layout将从application/layouts目录下寻找名称为layout.phtml的布局视图脚本,所以我
们最好写好这个文件,下面是这个文件的内容:
zf-tutorial/application/layouts/layout.phtml
<?php echo $this->doctype(); ?>
<html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”en” lang=”en”>
<head>
<?php echo $this->headMeta(); ?>
<?php echo $this->headTitle(); ?>
</head>
<body>
<div id=”content”>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php echo $this->layout()->content; ?>
</div>
</body>
</html>
布局文件包含非常标准的外层HTML代码。因为这个文件是个普通的PHP文件,我们可以在里面使用PHP。里面有
个变量$this,它是视图对象的一个实例,在程序引导时被创建。我们可以用它来获取已经赋给视图的数据,也
可以调用方法。这些方法(即视图助手view helpers)返回数据可以直接用echo输出。
首先输出Bootstrap::_initViewHelpers()中创建的脚本助手,它将为<head>部分创建准备的代码。在<body>
中,我们创建一个div层,div中有一个包含标题的<h1>。为了显示当前动作的显示脚本(view scripts),我们
使用了layout()辅助函数: echo $this->layout()->content;它将内容显示到content占位符中。这也意味着
动作的显示脚本在布局显示脚本之前执行。
在再测试一下上述四个URL,你会发现看到的内容与上次一模一样!然而它们有一个关键的不同,就是这次所有
的工作都是利用布局显示脚本(layout)来完成的。
样式
虽然只是一个教程,我们还是需要一个 CSS 文件来使得我们的程序看起来漂亮一些。因为 URL 并不是指向正
确的根目录,这使得我们在如何引用CSS文件时碰到一点小麻烦。
在zend Framework 1.9 中,引入视图助手baseUrl()。它可以从请求对象中收集我们需要的信息,提供我们不知
道的URL内容。
在zend Framework 1.8 中,还没有提供baseUrl()视图助手,所以我们要自己创建。视图助手放在application/
views/helpers子目录下,并被命名为{HelpName}.php (首字母必须大写),其中的类有一个预料中的命名规
则:必须被命名为Zend_View_Helper_{HelperName} (首字母必须大写)。类中必须有一个名为{helperName}()
(首字母小写,勿记!)的函数。在我们的例子中,这个文件命名为BaseUrl.php,内容如下:
zf-tutorial/application/views/helpers/BaseUrl.php
<?php
class Zend_View_Helper_BaseUrl
{
function baseUrl()
{
$fc = Zend_Controller_Front::getInstance();
return $fc->getBaseUrl();
}
}
这个函数并不复杂。我们简单地得到一个前端控制器的实例,然后返回getBaseUrl()成员函数的值。
注意在ZF1.8 和 1.9 中,如果你想创建自己的视图助手,创建过程都跟上面我们建立baseUrl()一样。
下面,我们需要添加CSS文件到application/layouts/layout.phtml的<head>部分,我们再使用一个视图助手-
headLink():
zf-tutorial/application/layouts/layout.phtml
…
<head>
<?php echo $this->HeadMeta(); ?>
<?php echo $this->headTitle(); ?>
<?php echo $this->headLink()->prependStylesheet($this->baseUrl().’/css/site.css’); ?>
</head>
…
利用headLink(),我们允许有其它特殊作用的CSS文件添加在控制器视图脚本中,它们将显示在<head>部分的
site.css之后。
最后,我们需要添加CSS样式,所以在public中创建一个css目录:
zf-tutorial/public/css/site.css
body,html {
margin: 0 5px;
font-family: Verdana,sans-serif;
}
h1 {
font-size: 1.4em;
color: #008000;
}
a {
color: #008000;
}
/* Table */
th {
text-align: left;
}
td, th {
padding-right: 5px;
}
/* style form */
form dt {
width: 100px; display: block; float: left; clear: left;
}
form dd {
margin-left: 0;
float: left;
}
form #submitbutton {
margin-left: 100px;
}
这会使它看起来稍微好看一些,但像你可能会说的那样,我不是个设计师(所以别指望太好看)!
现在我们可以清理前面为了填充内容而自动创建的四个动作脚本,清空index.phtml、add.phtml、add.phtml、
edit.html和delete.phtml (提醒一下,它们在application/view/scripts/index目录下)。
唱片列表功能
既然我们已经配置好配置文件、数据库和视图骨架,我们可以开始进行程序的中心内容,首先显示一个唱片的
列表。这在 IndexController 类中的 indexAction()函数中实现,开始时我们将唱片的列表在一个表格中显示
出来:
zf-tutorial/application/controllers/IndexController.php
…
function indexAction()
{
$this->view->title = “My Albums”;
$this->view->headTitle($this->view->title, ‘PREPEND’);
$albums = new Model_DbTable_Albums();
$this->view->albums = $albums->fetchAll();
}
…
首先我们为页面设置标题,然后把这引标题添加到head title的前面,显示在浏览器标题栏。
fetchAll函数返回一个Zend_Db_Table_Rowset对象,它允许我们在动作的视图脚本文件中遍历返回的记录。现
在我们可以填充相关的视图脚本index.phtml:
zf-tutorial/application/views/scripts/index/index.phtml
<p><a href=”<?php echo $this->url(array(‘controller’=>’index’,'action’=>’add’));?>”>Add new album</a></p>
<table>
<tr>
<th>Title</th>
<th>Artist</th>
<th> </th>
</tr>
<?php foreach($this->albums as $album) : ?>
<tr>
<td><?php echo $this->escape($album->title);?></td>
<td><?php echo $this->escape($album->artist);?></td>
<td>
<a href=”<?php echo $this->url(array(‘controller’=>’index’,
‘action’=>’edit’, ‘id’=>$album->id));?>”>Edit</a>
<a href=”<?php echo $this->url(array(‘controller’=>’index’,
‘action’=>’delete’, ‘id’=>$album->id));?>”>Delete</a>
</td>
</tr>
<?php endforeach; ?>
</table>
首先我们创建一下链向 “添加新唱片”的超链接。ZF提供的url()视图助手非常有助于创建包含正确baseurl的
超链接。我们只需要将需要的参数以数组的形式传递给它,剩下的工作它都自动完成。
下面我们创建一个html表格来显示每个唱片的标题和作者,并提供修改和删除唱片的链接。我们用一个标准的
foreach:循环来显示唱片列表。这里我们使用替代语法:用一个冒号和endforeach;,因为这样比使用配对大括号
更容易查看。同样的,我们可以使用url()视图助手来创建编辑和删除的链接。
打开http://localhost/zf-tutorial,应该显示一个不错的唱片列表
添加新唱片
我们可以开始编写添加新唱片的功能了。这部分包括两点:
• 提供一个表单让用户填写资料
• 处理提交的表单并添加到数据库中
我们使用Zend_From来做这个工作。Zend_Form组件可以用来创建表单和验证表单。我们创建一个扩展自
Zend_Form的新类Form_Album来定义我们的表单。因为我们使用模块自动加载,这个类应该存储在forms目录下
的Album.php文件中:
zf-tutorial/application/forms/Album.php
<?php
class Form_Album extends Zend_Form
{
public function construct($options = null)
{
parent:: construct($options);
$this->setName(‘album’);
$id = new Zend_Form_Element_Hidden(‘id’);
$artist = new Zend_Form_Element_Text(‘artist’);
$artist->setLabel(‘Artist’)
->setRequired(true)
->addFilter(‘StripTags’)
->addFilter(‘StringTrim’)
->addValidator(‘NotEmpty’);
$title = new Zend_Form_Element_Text(‘title’);
$title->setLabel(‘Title’)
->setRequired(true)
->addFilter(‘StripTags’)
->addFilter(‘StringTrim’)
->addValidator(‘NotEmpty’);
$submit = new Zend_Form_Element_Submit(‘submit’);
$submit->setAttrib(‘id’, ‘submitbutton’);
$this->addElements(array($id, $artist, $title, $submit));
}
}
在form_Album的构造函数中,我们创建四个表单元素,分别用作id、artist、title和submit按钮。我们给每个
元素设置不同的属性,包括要显示的label。对text元素,我们添加两个过滤器-StripTags和StringTrim,来移
除不想要的HTML代码和空格。我们也可以设置他们是必填项,通过添加一个NotEmpty验证器来保证用户确实输
入了我们需要的信息。
现在我们需要显示这个表单,然后在提交后进行处理。这结都在IndexController的addAction()中做到:
zf-tutorial/application/controllers/IndexController.php
…
function addAction()
{
$this->view->title = “Add new album”;
$this->view->headTitle($this->view->title, ‘PREPEND’);
$form = new Form_Album();
$form->submit->setLabel(‘Add’);
$this->view->form = $form;
if ($this->getRequest()->isPost()) {
$formData = $this->getRequest()->getPost();
if ($form->isValid($formData)) {
$artist = $form->getValue(‘artist’);
$title = $form->getValue(‘title’);
$albums = new Model_DbTable_Albums();
$albums->addAlbum($artist, $title);
$this->_redirect(‘/’);
} else {
$form->populate($formData);
}
}
}
…
下面详解部分细节:
$form = new Form_Album();
$form->submit->setLabel(‘Add’);
$this->view->form = $form;
我们实例化Form_Album,将提交按钮的lable设置为 “Add”,然后定义到视图中以备显示。
if ($this->getRequest()->isPost()) {
$formData = $this->getRequest()->getPost();
if ($form->isValid($formData)) {
如果请求对象的isPost()方法返回真(true)则表示表单已经提交,然后使用getPost()获取表单数据,使用
isValid成员函数来判断是否有效。
$artist = $form->getValue(‘artist’);
$title = $form->getValue(‘title’);
$albums = new Model_DbTable_Albums();
$albums->addAlbum($artist, $title);
如果表单有效,则实例化Model_DbTable_Albums模型类,然后用我们之前创建addAlbum()方法向数据库中添加
一条新记录。
$this->_redirect(‘/’);
在我们保存这条新唱片记录后,利用控制器的_redirect()方法使页面重定向到首页。
} else {
$form->populate($formData);
}
如果表单数据无效,则将用户刚才填写的数据填充表单,并再次显示表单。现在我们需要在add.phtml视图脚本
中显示表单:
zf-tutorial/application/views/scripts/index/add.phtml
<?php echo $this->form ;?>
如你所见,显示一个表单非常简单,就好像表单自己知道如何去显示一样。
编辑唱片
编辑唱片跟添加唱片差不多是一样的,所以代码也差不多:
zf-tutorial/application/controllers/IndexController.php
…
function editAction()
{
$this->view->title = “Edit album”;
$this->view->headTitle($this->view->title, ‘PREPEND’);
$form = new Form_Album();
$form->submit->setLabel(‘Save’);
$this->view->form = $form;
if ($this->getRequest()->isPost()) {
$formData = $this->getRequest()->getPost();
if ($form->isValid($formData)) {
$id = (int)$form->getValue(‘id’);
$artist = $form->getValue(‘artist’);
$title = $form->getValue(‘title’);
$albums = new Model_DbTable_Albums();
$albums->updateAlbum($id, $artist, $title);
$this->_redirect(‘/’);
} else {
$form->populate($formData);
}
} else {
$id = $this->_getParam(‘id’, 0);
if ($id > 0) {
$albums = new Model_DbTable_Albums();
$form->populate($albums->getAlbum($id));
}
}
}
让我们看一下与添加唱片的不同。首先,在为用户显示表单的时候,我们需要读取数据库的唱片的作者和标
题,填充在表单中。这是这个方法的最后一部分:
$id = $this->_getParam(‘id’, 0);
if ($id > 0) {
$albums = new Model_DbTable_Albums();
$form->populate($albums->getAlbum($id));
}
当页面请求不是POST的时候,这部分会被执行。我们使用_getParam()方法从请求中获得id。然后用模型查询数
据库,并将结果直接显示在表单中。
在验证完表单后,我们需要把数据更新到当前操作的数据库记录中。这个工作由模型中的updateAlbum()方法完
成:
$id = (int)$form->getValue(‘id’);
$artist = $form->getValue(‘artist’);
$title = $form->getValue(‘title’);
$albums = new Model_DbTable_Albums();
$albums->updateAlbum($id, $artist, $title);
视图模板跟add.phtml一样:
zf-tutorial/application/views/scripts/index/edit.phtml
<?php echo $this->form ;?>
现在你就可以添加和编辑唱片信息了。
删除唱片
为了完善程序,我们需要增加删除功能。需要在唱片列表页的每个唱片后面加一个删除链接,当点击击该链接
时相应的唱片记录就会被删除,但这样做是错误的。记住我们的HTTP规范,对于不可逆的操作,不应该使用
GET,而应使用POST。
当用户点击删除链接时我们应该显示一个确认表单,如果在用户选择了“是”,我们就进行删除操作。因为这
个表单非常简单,我们直接将表单的HTML代码写到视图中。
先写IndexController::deleteAction()中的动作代码:
zf-tutorial/application/controllers/IndexController.php
…
public function deleteAction()
{
$this->view->title = “Delete album”;
$this->view->headTitle($this->view->title, ‘PREPEND’);
if ($this->getRequest()->isPost()) {
$del = $this->getRequest()->getPost(‘del’);
if ($del == ‘Yes’) {
$id = $this->getRequest()->getPost(‘id’);
$albums = new Model_DbTable_Albums();
$albums->deleteAlbum($id);
}
$this->_redirect(‘/’);
} else {
$id = $this->_getParam(‘id’, 0);
$albums = new Model_DbTable_Albums();
$this->view->album = $albums->getAlbum($id);
}
}
…
和添加和编辑时一样,我们通过使用请求对象的isPost()方法来确定是显示确认表单还是进行删除操作。实际
的删除操作是通过调用Model_DbTable_Albums()的deleteAlbum()方法来删除记录的。如果不是POST请求,就通
过id参数将相应的记录从数据库中读取出来并保存至视图中。
视图脚本是个简单的表单:
zf-tutorial/application/views/scripts/index/delete.phtml
<p>Are you sure that you want to delete
‘<?php echo $this->escape($this->album['title']); ?>’ by
‘<?php echo $this->escape($this->album['artist']); ?>’?
</p>
<form action=”<?php echo $this->url(array(‘action’=>’delete’)); ?>” method=”post”>
<div>
<input type=”hidden” name=”id” value=”<?php echo $this->album['id']; ?>” />
<input type=”submit” name=”del” value=”Yes” />
<input type=”submit” name=”del” value=”No” />
</div>
在这个脚本中,我们先给用户显示一条警告信息,然后是一个包含 “Yes”和 “No”按钮的表单。在动作代码中
做删除操作时先检查是否含有“Yes”值。
现在你有了一个完整可用的程序了。