要求Zend Framework要求PHP5。为了更好利用本教程的 代码,你还需要Apache 网页 服务器。因为示范程序(一个新闻管理系统)用到了 mod_rewrite。  这个教程的代码可以自由 下载,所以你可以自己试一下。你可以从Brain Buld的网站下载到代码: http://brainbulb.com/zend-framework-tutorial.tar.gz

下载ZF当你开始这篇教程时,你需要下载ZF的最新版本。你可以用 浏览器手工从 http://framework.zend.com/download选择 tar.gzzip 文件进行下载,或者使用下列 命令
  1. $ wget http://framework.zend.com/download/tgz
  2. $ tar -xvzf ZendFramework-0.1.2.tar.gz
复制代码
  提示:Zend计划提供自有PEAR通道简化下载。 一旦你下载了预览版,把 library 目录放到方便的地方。在这个教程,我把 library 重命名为 lib 以便有个简洁的目录结构:
app/
     views/
     controllers/
www/
     .htaccess
     index.php
lib/
www 目录是文档根目录, 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 类包含了一些经常使用的静态方法的集合。下面是唯一一个你要手工添加的类:
  1. <?php
  2. include ‘Zend.php’;
  3. ?>
复制代码


一旦你包含了 Zend.php ,你就已经包含了 Zend 类的所有的类方法。用 loadClass() 就可以简单地加载其它类。例如,加载 Zend_Controller_Front 类:
  1. <?php
  2. include ‘Zend.php’;
  3. Zend::loadClass(’Zend_Controller_Front’);
  4. ?>
复制代码


include_path 能理解 loadclass() 及ZF的组织和目录结构。我用它加载所有其它类。   

Zend_Controller使用这个controller非常直观。事实上,我写本教程时并没有用到它丰富的文档。  提示:文档目前已经可以在
http://framework.zend.com/manual/zend.controller.html 看到。  我一开始是用一个叫 Zend_Controller_Front 的front controller。为了理解它是怎么工作的,请把下列代码放在你的 index.php 文件:
  1. <?php
  2. include ‘Zend.php’;
  3. Zend::loadClass(’Zend_Controller_Front’);
  4. $controller = Zend_Controller_Front::getInstance();
  5. $controller->setControllerDirectory(’/path/to/controllers’);
  6. $controller->dispatch();
  7. ?>
复制代码
如果你更喜欢对象链结,可以用以下代码代替:
  1. <?php
  2. include ‘Zend.php’;
  3. Zend::loadClass(’Zend_Controller_Front’);
  4. $controller = Zend_Controller_Front::getInstance()
  5.                ->setControllerDirectory(’/path/to/controllers’)
  6.                ->dispatch();
  7. ?>
复制代码
现在如果你访问 /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() 设置):
  1. <?php
  2. Zend::loadClass(’Zend_Controller_Action’);
  3. class IndexController extends Zend_Controller_Action
  4. {
  5.      public function indexAction()
  6.      {
  7.          echo ‘IndexController::indexAction()’;
  8.      }
  9. }
  10. ?>
复制代码
就如刚才说明的, 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 :
  1. <?php
  2. Zend::loadClass(’Zend_Controller_Action’);
  3. class IndexController extends Zend_Controller_Action
  4. {
  5.      public function indexAction()
  6.      {
  7.          echo ‘IndexController::indexAction()’;
  8.      }
  9.      public function noRouteAction()
  10.      {
  11. $this->_redirect(’/');
  12.      }
  13. }
  14. ?>
复制代码
例子中使用 $this->_redirect('/') 来描述执行 noRouteAction() 时,可能发生的行为。这会将对不存在controllers的访问重定向到根文档(首页)。  现在创建 FooController.php
  1. <?php
  2. Zend::loadClass(’Zend_Controller_Action’);
  3. class FooController extends Zend_Controller_Action
  4. {
  5.      public function indexAction()
  6.      {
  7.          echo ‘FooController::indexAction()’;
  8.      }
  9.      public function barAction()
  10.      {
  11.          echo ‘FooController::barAction()’;
  12.      }
  13. }
  14. ?>
复制代码
如果你再次访问 /foo/bar ,你会发现执行了 barAction() ,因为 bar 是action。现在你不只支持了友好的URL,还可以只用几行代码就做得这么有条理。酷吧! 你也可以创建一个 __call() 类方法来处理像 /foo/baz 这样未定义的action。
  1. <?php
  2. Zend::loadClass(’Zend_Controller_Action’);
  3. class FooController extends Zend_Controller_Action
  4. {
  5.      public function indexAction()
  6.      {
  7.          echo ‘FooController::indexAction()’;
  8.      }
  9.      public function barAction()
  10.      {
  11.          echo ‘FooController::barAction()’;
  12.      }
  13.      public function __call($action, $arguments)
  14.      {
  15.          echo ‘FooController:__call()’;
  16.      }
  17. }
  18. ?>
复制代码
现在你只要几行代码就可以很好地处理用户的访问了,准备好继续。

Zend_View
Zend_View 是一个用来帮助你组织好你的view逻辑的类。这对于模板-系统是不可知的,为了简单起见,本教程不使用模板。如果你喜欢的话,不妨用一下。  记住,现在所有的访问都是由front controller进行处理。因此应用框架已经存在了,另外也必须遵守它。为了展示 Zend_View 的一个基本应用,将 IndexController.php 修改如下:
  1. <?php
  2. Zend::loadClass(’Zend_Controller_Action’);
  3. Zend::loadClass(’Zend_View’);
  4. class IndexController extends Zend_Controller_Action
  5. {
  6.      public function indexAction()
  7.      {
  8. $view = new Zend_View();
  9. $view->setScriptPath(’/path/to/views’);
  10.          echo $view->render(’example.php’);
  11.      }
  12.      public function noRouteAction()
  13.      {
  14. $this->_redirect(’/');
  15.      }
  16. }
  17. ?>
复制代码
views 目录创建 example.php 文件:
  1. <html>
  2. <head>
  3.      <title>This Is an Example</title>
  4. </head>
  5. <body>
  6.      <p>This is an example.</p>
  7. </body>
  8. </html>
复制代码
现在,如果你访问自己网站的根资源,你会看到 example.php 的内容。这仍没什么用,但你要清楚你要在以一种结构和组织非常清楚的方式在开发网络应用。  为了让 Zend_View 的应用更清楚一点,,修改你的模板( example.php )包含以下内容:
  1. <html>
  2. <head>
  3.      <title><?php echo $this->escape($this->title); ?></title>
  4. </head>
  5. <body>
  6. <?php echo $this->escape($this->body); ?>
  7. </body>
  8. </html>
复制代码
现在已经添加了两个功能。 $this->escape() 类方法用于所有的输出。即使你自己创建输出,就像这个例子一样。避开所有输出也是一个很好的习惯,它可以在默认情况下帮助你防止跨站脚本***(XSS)。   $this->title $this->body 属性用来展示动态数据。这些也可以在controller中定义,所以我们修改 IndexController.php 以指定它们:
  1. <?php
  2. Zend::loadClass(’Zend_Controller_Action’);
  3. Zend::loadClass(’Zend_View’);
  4. class IndexController extends Zend_Controller_Action
  5. {
  6.      public function indexAction()
  7.      {
  8. $view = new Zend_View();
  9. $view->setScriptPath(’/path/to/views’);
  10. $view->title = ‘Dynamic Title’;
  11. $view->body = ‘This is a dynamic body.’;
  12.          echo $view->render(’example.php’);
  13.      }
  14.      public function noRouteAction()
  15.      {
  16. $this->_redirect(’/');
  17.      }
  18. }
  19. ?>
复制代码


现在你再次访问根目录,应该就可以看到模板所使用的这些值了。因为你在模板中使用的 $this 就是在 Zend_View 范围内所执行的实例。 要记住 example.php 只是一个普通的PHP脚本,所以你完全可以做你想做的。只是应努力只在要求显示数据时才使用模板。你的controller (controller分发的模块)应处理你全部的业务逻辑。  在继续之前,我想做最后一个关于 Zend_View 的提示。在controller的每个类方法内初始化 $view 对象需要额外输入一些内容,而我们的主要目标是让快速开发网络应用更简单。如果所有模板都放在一个目录下,是否要在每个例子中都调用 setScriptPath() 也存在争议。 幸运的是, Zend 类包含了一个寄存器来帮助减少工作量。你可以用 register() 方法把你的 $view 对象存储在寄存器:
  1. <?php
  2. Zend::register(’view’, $view);
  3. ?>
复制代码
registry() 方法进行检索:
  1. <?php
  2. $view = Zend::registry(’view’);
  3. ?>
复制代码
基于这点,本教程使用寄存器。  

Zend_InputFilter本教程讨论的最后一个组件是
Zend_InputFilter 。这个类提供了一种简单而有效的输入过滤方法。你可以通过提供一组待过滤数据来进行初始化。
  1. <?php
  2. $filterPost = new Zend_InputFilter($_POST);
  3. ?>
复制代码


这会将( $_POST )设置为 NULL ,所以就不能直接进入了。 Zend_InputFilter 提供了一个简单、集中的根据特定规则过滤数据的类方法集。例如,你可以用 getAlpha() 来获取 $_POST['name'] 中的字母:
  1. <?php
  2. /* $_POST['name'] = ‘John123Doe’; */
  3. $filterPost = new Zend_InputFilter($_POST);
  4. /* $_POST = NULL; */
  5. $alphaName = $filterPost->getAlpha(’name’);
  6. /* $alphaName = ‘JohnDoe’; */
  7. ?>
复制代码


每一个类方法的参数都是对应要过滤的元素的关键词。对象(例子中的 $filterPost )可以保护数据不被篡改,并能更好地控制对数据的操作及一致性。因此,当你操纵输入数据,应始终使用 Zend_InputFilter 。  提示: Zend_Filter 提供与 Zend_InputFilter 方法一样的静态方法。