侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Zend Framework开发入门经典教程

框架(架构)  /  管理员 发布于 7年前   118

本文讲述了Zend Framework开发入门相关知识点。分享给大家供大家参考,具体如下:

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
lib/

www目录是文档根目录,controllers和views目录是以后会用到的空目录,而lib目录来自你下载的预览版。

开始

我要介绍的第一个组件是Zend_Controller。从很多方面看,它为你开发的程序提供了基础,同时也部分决定了Zend Framework不只是个组件的集合。但是,你在用之前需要将所有的得到的请求都放到一个简单的PHP脚本。本教程用的是mod_rewrite。

用mod_rewrite自身是一种艺术,但幸运的是,这个特殊的任务特别简单。如果你对mod_rewrite或Apache的一般配置不熟悉,在文档根目录下创建一个.htaccess文件,并添加以下内容:

RewriteEngine onRewriteRule !/.(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类包含了一些经常使用的静态方法的集合。下面是唯一一个你要手工添加的类:

一旦你包含了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文件:

setControllerDirectory('/path/to/controllers');$controller->dispatch();?>

如果你更喜欢对象链结,可以用以下代码代替:

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()设置):

就如刚才说明的,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:

_redirect('/');  }}?>

例子中使用$this->_redirect('/')来描述执行noRouteAction()时,可能发生的行为。这会将对不存在controllers的访问重定向到根文档(首页)。

现在创建FooController.php:

如果你再次访问/foo/bar,你会发现执行了barAction(),因为bar是action。现在你不只支持了友好的URL,还可以只用几行代码就做得这么有条理。酷吧!
你也可以创建一个__call()类方法来处理像/foo/baz这样未定义的action。

现在你只要几行代码就可以很好地处理用户的访问了,准备好继续。

Zend_View

Zend_View是一个用来帮助你组织好你的view逻辑的类。这对于模板-系统是不可知的,为了简单起见,本教程不使用模板。如果你喜欢的话,不妨用一下。

记住,现在所有的访问都是由front controller进行处理。因此应用框架已经存在了,另外也必须遵守它。为了展示Zend_View的一个基本应用,将IndexController.php修改如下:

setScriptPath('/path/to/views');    echo $view->render('example.php');  }  public function noRouteAction()  {    $this->_redirect('/');  }}?>

在views目录创建example.php文件:

  This Is an Example  

This is an example.

现在,如果你访问自己网站的根资源,你会看到example.php的内容。这仍没什么用,但你要清楚你要在以一种结构和组织非常清楚的方式在开发网络应用。

为了让Zend_View的应用更清楚一点,,修改你的模板(example.php)包含以下内容:

  <?php echo $this->escape($this->title); ?>  escape($this->body); ?>

现在已经添加了两个功能。$this->escape()类方法用于所有的输出。即使你自己创建输出,就像这个例子一样。避开所有输出也是一个很好的习惯,它可以在默认情况下帮助你防止跨站脚本攻击(XSS)。

$this->title和$this->body属性用来展示动态数据。这些也可以在controller中定义,所以我们修改IndexController.php以指定它们:

setScriptPath('/path/to/views');    $view->title = 'Dynamic Title';    $view->body = 'This is a dynamic body.';    echo $view->render('example.php');  }  public function noRouteAction()  {    $this->_redirect('/');  }}?>

现在你再次访问根目录,应该就可以看到模板所使用的这些值了。因为你在模板中使用的$this就是在Zend_View范围内所执行的实例。

要记住example.php只是一个普通的PHP脚本,所以你完全可以做你想做的。只是应努力只在要求显示数据时才使用模板。你的controller (controller分发的模块)应处理你全部的业务逻辑。

在继续之前,我想做最后一个关于Zend_View的提示。在controller的每个类方法内初始化$view对象需要额外输入一些内容,而我们的主要目标是让快速开发网络应用更简单。如果所有模板都放在一个目录下,是否要在每个例子中都调用setScriptPath()也存在争议。

幸运的是,Zend类包含了一个寄存器来帮助减少工作量。你可以用register()方法把你的$view对象存储在寄存器:

用registry()方法进行检索:

基于这点,本教程使用寄存器。 

Zend_InputFilter

本教程讨论的最后一个组件是Zend_InputFilter。这个类提供了一种简单而有效的输入过滤方法。你可以通过提供一组待过滤数据来进行初始化。

这会将($_POST)设置为NULL,所以就不能直接进入了。Zend_InputFilter提供了一个简单、集中的根据特定规则过滤数据的类方法集。例如,你可以用getAlpha()来获取$_POST['name']中的字母:

getAlpha('name');/* $alphaName = 'JohnDoe'; */?>

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

提示:Zend_Filter提供与Zend_InputFilter方法一样的静态方法。

构建新闻管理系统

虽然预览版提供了许多组件(甚至许多已经被开发),我们已经讨论了构建一个简单程序所需要的全部组件。在这里,你会对ZF的基本结构和设计有更清楚的理解。

每个人开发的程序都会有所不同,而Zend Framework试图包容这些差异。同样,这个教程是根据我的喜好写的,请根据自己的偏好自行调整。

当我开发程序时,我会先做界面。这并不意味着我把时间都花在标签、样式表和图片上,而是我从一个用户的角度去考虑问题。因此我把程序看成是页面的集合,每一页都是一个独立的网址。这个新闻系统就是由以下网址组成的:

/
/add/news
/add/comment
/admin
/admin/approve
/view/{id}

你可以直接把这些网址和controller联系起来。IndexController列出新闻,AddController添加新闻和评论,AdminController处理一些如批准新闻之类的管理,ViewController特定新闻和对应评论的显示。

如果你的FooController.php还在,把它删除。修改IndexController.php,为业务逻辑以添加相应的action和一些注释:

_redirect('/');  }}?>

接下来,创建AddController.php文件:

_redirect('/');  }  function commentAction()  {    /* Add a comment. */  }  function newsAction()  {    /* Add news. */  }  function __call($action, $arguments)  {    $this->_redirect('/');  }}?>

记住AddController的indexAction()方法不能调用。当访问/add时会执行这个类方法。因为用户可以手工访问这个网址,这是有可能的,所以你要把用户重定向到主页、显示错误或你认为合适的行为。

接下来,创建AdminController.php文件:

_redirect('/');  }}?>

最后,创建ViewController.php文件:

_redirect('/');  }  function __call($id, $arguments)  {    /* Display news and comments for $id. */  }}?>

和AddController一样,index()方法不能调用,所以你可以使用你认为合适的action。ViewController和其它的有点不同,因为你不知道什么才是有效的action。为了支持像/view/23这样的网址,你要使用__call()来支持动态action。

数据库操作

因为Zend Framework的数据库组件还不稳定,而我希望这个演示可以做得简单一点。我使用了一个简单的类,用SQLite进行新闻条目和评论的存储和查询。

_db = new SQLiteDatabase($filename);  }  public function addComment($name, $comment, $newsId)  {    $name = sqlite_escape_string($name);    $comment = sqlite_escape_string($comment);    $newsId = sqlite_escape_string($newsId);    $sql = "INSERT        INTO  comments (name, comment, newsId)        VALUES ('$name', '$comment', '$newsId')";    return $this->_db->query($sql);  }  public function addNews($title, $content)  {    $title = sqlite_escape_string($title);    $content = sqlite_escape_string($content);    $sql = "INSERT        INTO  news (title, content)        VALUES ('$title', '$content')";    return $this->_db->query($sql);  }  public function approveNews($ids)  {    foreach ($ids as $id) {      $id = sqlite_escape_string($id);      $sql = "UPDATE news          SET  approval = 'T'          WHERE id = '$id'";      if (!$this->_db->query($sql)) {        return FALSE;      }    }    return TRUE;  }  public function getComments($newsId)  {    $newsId = sqlite_escape_string($newsId);    $sql = "SELECT name, comment        FROM  comments        WHERE newsId = '$newsId'";    if ($result = $this->_db->query($sql)) {      return $result->fetchAll();    }    return FALSE;  }  public function getNews($id = 'ALL')  {    $id = sqlite_escape_string($id);    switch ($id) {      case 'ALL':        $sql = "SELECT id,    titleFROM  newsWHERE approval = 'T'";        break;      case 'NEW':        $sql = "SELECT *FROM  newsWHERE approval != 'T'";        break;      default:        $sql = "SELECT *FROM  newsWHERE id = '$id'";        break;    }    if ($result = $this->_db->query($sql)) {      if ($result->numRows() != 1) {        return $result->fetchAll();      } else {        return $result->fetch();      }    }    return FALSE;  }}?>

(你可以用自己的解决方案随意替换这个类。这里只是为你提供一个完整示例的介绍,并非建议要这么实现。)

这个类的构造器需要SQLite数据库的完整路径和文件名,你必须自己进行创建。

query("CREATE TABLE news (    id    INTEGER PRIMARY KEY,    title  VARCHAR(255),    content TEXT,    approval CHAR(1) DEFAULT 'F'  )");$db->query("CREATE TABLE comments (    id    INTEGER PRIMARY KEY,    name   VARCHAR(255),    comment TEXT,    newsId  INTEGER  )");?>

你只需要做一次,以后直接给出Database类构造器的完整路径和文件名即可:

整合

为了进行整合,在lib目录下创建Database.php,loadClass()就可以找到它。你的index.php文件现在就会初始化$view和$db并存储到寄存器。你也可以创建__autoload()函数自动加载你所需要的类:

setScriptPath('/path/to/views');Zend::register('view', $view);$controller = Zend_Controller_Front::getInstance()       ->setControllerDirectory('/path/to/controllers')       ->dispatch();?>

接下来,在views目录创建一些简单的模板。index.php可以用来显示index视图:

 News 

News

news as $entry) { ?>

escape($entry['title']); ?>

Add News

Title:

Content:

view.php模板可以用来显示选定的新闻条目:

   <?php echo $this->escape($this->news['title']); ?>  

escape($this->news['title']); ?>

escape($this->news['content']); ?>

Comments

comments as $comment) { ?>

escape($comment['name']); ?> writes:

escape($comment['comment']); ?>

Add a Comment

Name:

Comment:

最后,admin.php模板可以用来批准新闻条目:

 News Admin 
news as $entry) { ?>

escape($entry['title']); ?> escape($entry['content']); ?>

Password:

提示:为了保持简单,这个表单用密码作为验证机制。

使用到模板的地方,你只需要把注释替换成几行代码。如IndexController.php就变成下面这样:

news = $db->getNews();    echo $view->render('index.php');  }  public function noRouteAction()  {    $this->_redirect('/');  }}?>

因为条理比较清楚,这个程序首页的整个业务逻辑只有四行代码。AddController.php更复杂一点,它需要更多的代码:

_redirect('/');  }  function commentAction()  {    /* Add a comment. */    $filterPost = new Zend_InputFilter($_POST);    $db = Zend::registry('db');    $name = $filterPost->getAlpha('name');    $comment = $filterPost->noTags('comment');    $newsId = $filterPost->getDigits('newsId');    $db->addComment($name, $comment, $newsId);    $this->_redirect("/view/$newsId");  }  function newsAction()  {    /* Add news. */    $filterPost = new Zend_InputFilter($_POST);    $db = Zend::registry('db');    $title = $filterPost->noTags('title');    $content = $filterPost->noTags('content');    $db->addNews($title, $content);    $this->_redirect('/');  }  function __call($action, $arguments)  {    $this->_redirect('/');  }}?>

因为用户在提交表单后被重定向,这个controller不需要视图。

在AdminController.php,你要处理显示管理界面和批准新闻两个action:

news = $db->getNews('NEW');    echo $view->render('admin.php');  }  function approveAction()  {    /* Approve news. */    $filterPost = new Zend_InputFilter($_POST);    $db = Zend::registry('db');    if ($filterPost->getRaw('password') == 'mypass') {      $db->approveNews($filterPost->getRaw('ids'));      $this->_redirect('/');    } else {      echo 'The password is incorrect.';    }  }  function __call($action, $arguments)  {    $this->_redirect('/');  }}?>

最后是ViewController.php:

_redirect('/');  }  function __call($id, $arguments)  {    /* Display news and comments for $id. */    $id = Zend_Filter::getDigits($id);    $db = Zend::registry('db');    $view = Zend::registry('view');    $view->news = $db->getNews($id);    $view->comments = $db->getComments($id);    $view->id = $id;    echo $view->render('view.php');  }}?>

虽然很简单,但我们还是提供了一个功能较全的新闻和评论程序。最好的地方是由于有较好的设计,增加功能变得很简单。而且随着Zend Framework越来越成熟,只会变得更好。

更多信息

这个教程只是讨论了ZF表面的一些功能,但现在也有一些其它的资源可供参考。在http://framework.zend.com/manual/有手册可以查询,Rob Allen在http://akrabat.com/zend-framework/介绍了一些他使用Zend Framework的经验,而Richard Thomas也在http://www.cyberlot.net/zendframenotes提供了一些有用的笔记。如果你有自己的想法,可以访问Zend Framework的新论坛:http://www.phparch.com/discuss/index.php/f/289//。

结束语

要对预览版进行评价是很容易的事,我在写这个教程时也遇到很多困难。总的来说,我想Zend Framework显示了承诺,加入的每个人都是想继续完善它。

更多关于zend相关内容感兴趣的读者可查看本站专题:《Zend FrameWork框架入门教程》、《php优秀开发框架总结》、《Yii框架入门及常用技巧总结》、《ThinkPHP入门教程》、《php面向对象程序设计入门教程》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

希望本文所述对大家基于Zend Framework框架的PHP程序设计有所帮助。

您可能感兴趣的文章:

  • Zend Framework 2.0事件管理器(The EventManager)入门教程
  • Zend Framework数据库操作技巧总结
  • Zend Framework数据库操作方法实例总结
  • Zend Framework入门教程之Zend_Db数据库操作详解
  • ZendFramework框架实现连接两个或多个数据库的方法
  • Zend Framework教程之连接数据库并执行增删查的方法(附demo源码下载)
  • Zend Framework连接Mysql数据库实例分析
  • 解析如何使用Zend Framework 连接数据库
  • zend framework配置操作数据库实例分析
  • windows下zendframework项目环境搭建(通过命令行配置)
  • zend framework多模块多布局配置
  • ZendFramework2连接数据库操作实例


  • 上一条:
    Zend Framework教程之Zend_Db_Table表关联实例详解
    下一条:
    Zend Framework教程之Zend_Config_Ini用法分析
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Filament v3.1版本发布(0个评论)
    • docker + gitea搭建一个git服务器流程步骤(0个评论)
    • websocket的三种架构方式使用优缺点浅析(0个评论)
    • ubuntu20.4系统中宿主机安装nginx服务,docker容器中安装php8.2实现运行laravel10框架网站(0个评论)
    • phpstudy_pro(小皮面板)中安装最新php8.2.9版本流程步骤(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2018-05
    • 2020-02
    • 2020-03
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-11
    • 2021-03
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-08
    • 2023-08
    • 2023-10
    • 2023-12
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客