引用:
我们邀请PHP安全专家 — 最新版Zend Frame的贡献者 — Chris Shiflett帮我们写一篇文章介绍一下ZF的主要细节,他爽快地答应了! 这份手把手的完整教程提供了用ZF构建实例的方法,并教你如何编写一个新闻管理系统。
在我们的论坛上讨论ZF和这篇教程。
Zend
Framework发布了!虽然仍处于开发初期,这个教程仍突出讲解目前几个最好的功能,并指导你完成一个简单程序的构建。
Zend最早在
社区里发布了ZF。基于同样的想法,这个教程写来用于展示ZF现有的功能。由于这个教程是在线发布,我将在ZF变化时对其进行更新,以便尽可能有效。
要求
Zend Framework要求PHP5。为了更好利用本教程的代码,你还需要Apache网页
服务器。因为示范程序(一个新闻管理系统)用到了
mod_rewrite。
这个教程的代码可以自由
下载,所以你可以自己试一下。你可以从Brain Buld的网站下载到代码:
http://brainbulb.com/zend-framework-tutorial.tar.gz。
下载ZF
当你开始这篇教程时,你需要下载ZF的最新版本。你可以用
浏览器手工从
http://framework.zend.com/download选择
tar.gz或
zip文件进行下载,或者使用下列命令:
复制内容到剪贴板
代码:
$ wget http://framework.zend.com/download/tgz
$ tar -xvzf ZendFramework-0.1.2.tar.gz提示:Zend计划提供自有
PEAR通道简化下载。
一旦你下载了预览版,把
library目录放到方便的地方。在这个教程,我把
library重命名为
lib以便有个简洁的目录结构:
复制内容到剪贴板
代码:
app/
views/
controllers/
www/
.htaccess
index.php
libwww目录是
文档根目录,
controllers和
views目录是以后会用到的空目录,而
lib目录来自你下载的预览版。
开始
我要介绍的第一个
组件是
Zend_Controller。从很多方面看,它为你开发的程序提供了基础,同时也部分决定了Zend Framework不只是个组件的集合。但是,你在用之前需要将所有的得到的请求都放到一个简单的PHP脚本。本教程用的是
mod_rewrite。
用
mod_rewrite自身是一种艺术,但幸运的是,这个特殊的任务特别简单。如果你对
mod_rewrite或Apache的一般配置不熟悉,在文档根目录下创建一个
.htaccess文件,并添加以下内容:
复制内容到剪贴板
代码:
RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php提示: Zend_Controller的一个TODO项目就是取消对
mod_rewrite的依赖。为了提供一个预览版的范例,本教程用了
mod_rewrite。
如果你直接把这些内容添加到
httpd.conf,你必须重启网页服务器。但如果你用
.htaccess文件,则什么都不必做。你可以放一些具体的文本到
index.php并访问任意路径如
/foo/bar做一下快速测试。如你的域名为
example.org,则访问
http://example.org/foo/bar。
你还要设置ZF库的路径到
include_path。你可以在
php.ini设置,也可以直接在你的
.htaccess文件放下列内容:
php_value include_path "/path/to/lib"
Zend
Zend类包含了一些经常使用的静态方法的集合。下面是唯一一个你要手工添加的类:
复制内容到剪贴板
代码:
<?php
include 'Zend.php';
?>一旦你包含了
Zend.php,你就已经包含了
Zend类的所有的类方法。用
loadClass()就可以简单地加载其它类。例如,加载
Zend_Controller_Front类:
复制内容到剪贴板
代码:
<?php
include 'Zend.php';
Zend::loadClass('Zend_Controller_Front');
?>include_path能理解
loadclass()及ZF的组织和目录结构。我用它加载所有其它类。
Zend_Controller
使用这个controller非常直观。事实上,我写本教程时并没有用到它丰富的文档。
提示:文档目前已经可以在
http://framework.zend.com/manual/zend.controller.html看到。
我一开始是用一个叫
Zend_Controller_Front的front controller。为了理解它是怎么工作的,请把下列代码放在你的
index.php文件:
复制内容到剪贴板
代码:
<?php
include 'Zend.php';
Zend::loadClass('Zend_Controller_Front');
$controller = Zend_Controller_Front::getInstance();
$controller->setControllerDirectory('/path/to/controllers');
$controller->dispatch();
?>如果你更喜欢对象链结,可以用以下代码代替:
复制内容到剪贴板
代码:
<?php
include 'Zend.php';
Zend::loadClass('Zend_Controller_Front');
$controller = Zend_Controller_Front::getInstance()
->setControllerDirectory('/path/to/controllers')
->dispatch();
?>现在如果你访问
/foo/bar,会有错误发生。没错!它让你知道发生了什么事。主要的问题是找不到
IndexController.php文件。
在你创建这个文件之前,应先理解一下ZF想让你怎样组织这些事情。ZF把访问请求给拆分开来。假如访问的是
/foo/bar,则
foo是controller,而
bar是action。它们的默认值都是
index.
如果
foo是controller,ZF就会去查找
controllers目录下的
FooController.php文件。因为这个文件不存在,ZF就退回到
IndexController.php。结果都没有找到,就报错了。
接下来,在
controllers目录创建
IndexController.php文件(可以用
setControllerDirectory()设置):
复制内容到剪贴板
代码:
<?php
Zend::loadClass('Zend_Controller_Action');
class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
echo 'IndexController::indexAction()';
}
}
?>就如刚才说明的,
IndexController类处理来自
index controller或controller不存在的请求。
indexAction()方法处理action为
index的访问。要记住的是
index是controller和action的默认值。如果你访问
/,
/index或
/index/index,
indexAction()方法就会被执行。 (最后面的斜杠并不会改变这个行为。) 而访问其他任何资源只会导致出错。
在继续做之前,还要在
IndexController加上另外一个有用的类方法。不管什么时候访问一个不存在的
控制器,都要调用
noRouteAction()类方法。例如,在
FooController.php不存在的条件下,访问
/foo/bar就会执行
noRouteAction()。但是访问
/index/foo仍会出错,因为
foo是action,而不是controller.
将
noRouteAction()添加到
IndexController.php:
复制内容到剪贴板
代码:
<?php
Zend::loadClass('Zend_Controller_Action');
class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
echo 'IndexController::indexAction()';
}
public function noRouteAction()
{
$this->_redirect('/');
}
}
?>例子中使用
$this->_redirect('/')来描述执行
noRouteAction()时,可能发生的行为。这会将对不存在controllers的访问重定向到根文档(首页)。
现在创建
FooController.php:
复制内容到剪贴板
代码:
<?php
Zend::loadClass('Zend_Controller_Action');
class FooController extends Zend_Controller_Action
{
public function indexAction()
{
echo 'FooController::indexAction()';
}
public function barAction()
{
echo 'FooController::barAction()';
}
}
?>
如果你再次访问/foo/bar,你会发现执行了barAction(),因为bar是action。现在你不只支持了友好的URL,还可以只用几行代码就做得这么有条理。酷吧!
你也可以创建一个__call()类方法来处理像/foo/baz这样未定义的action。
复制内容到剪贴板
代码:
<?php
Zend::loadClass('Zend_Controller_Action');
class FooController extends Zend_Controller_Action
{
public function indexAction()
{
echo 'FooController::indexAction()';
}
public function barAction()
{
echo 'FooController::barAction()';
}
public function __call($action, $arguments)
{
echo 'FooController:__call()';
}
}
?>
现在你只要几行代码就可以很好地处理用户的访问了,准备好继续。