ZF学习实例.doc_第1页
ZF学习实例.doc_第2页
ZF学习实例.doc_第3页
ZF学习实例.doc_第4页
ZF学习实例.doc_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

技术论坛 精彩日志 教程文章 资源下载 关于本站 首页 教程文章 文章查看 Zend Framework实例教程作者:张佳(译) 来源:PHPEye开源社区 2006-11-07 最后更新:2006-12-19 15:42:16 收藏: 最新更新:2006年3月11日我们邀请PHP安全专家 最新版Zend Frame的贡献者 Chris Shiflett帮我们写一篇文章介绍一下ZF的主要细节,他爽快地答应了! 这份手把手的完整教程提供了用ZF构建实例的方法,并教你如何编写一个新闻管理系统。 在我们的论坛上讨论ZF和这篇教程。 Brain Bulb Zend Framework发布了!虽然仍处于开发初期,这个教程仍突出讲解目前几个最好的功能,并指导你完成一个简单程序的构建。 Zend最早在社区里发布了ZF。基于同样的想法,这个教程写来用于展示ZF现有的功能。由于这个教程是在线发布,我将在ZF变化时对其进行更新,以便尽可能有效。 要求Zend Framework要求PHP5。为了更好利用本教程的代码,你还需要Apache网页服务器。因为示范程序(一个新闻管理系统)用到了mod_rewrite。 这个教程的代码可以自由下载,所以你可以自己试一下。你可以从Brain Buld的网站下载到代码:/zend-framework-tutorial.tar.gz。 下载ZF当你开始这篇教程时,你需要下载ZF的最新版本。你可以用浏览器手工从/download选择tar.gz或zip文件进行下载,或者使用下列命令: $wget/download/tgz$tar-xvzfZendFramework-0.1.2.tar.gz提示:Zend计划提供自有PEAR通道简化下载。一旦你下载了预览版,把library目录放到方便的地方。在这个教程,我把library重命名为lib以便有个简洁的目录结构: app/views/controllers/www/.htaccessindex.phplib/www目录是文档根目录,controllers和views目录是以后会用到的空目录,而lib目录来自你下载的预览版。 开始我要介绍的第一个组件是Zend_Controller。从很多方面看,它为你开发的程序提供了基础,同时也部分决定了Zend Framework不只是个组件的集合。但是,你在用之前需要将所有的得到的请求都放到一个简单的PHP脚本。本教程用的是mod_rewrite。 用mod_rewrite自身是一种艺术,但幸运的是,这个特殊的任务特别简单。如果你对mod_rewrite或Apache的一般配置不熟悉,在文档根目录下创建一个.htaccess文件,并添加以下内容: RewriteEngineonRewriteRule!.(js|ico|gif|jpg|png|css)$index.php提示: Zend_Controller的一个TODO项目就是取消对mod_rewrite的依赖。为了提供一个预览版的范例,本教程用了mod_rewrite。如果你直接把这些内容添加到httpd.conf,你必须重启网页服务器。但如果你用.htaccess文件,则什么都不必做。你可以放一些具体的文本到index.php并访问任意路径如/foo/bar做一下快速测试。如你的域名为,则访问/foo/bar。 你还要设置ZF库的路径到include_path。你可以在php.ini设置,也可以直接在你的.htaccess文件放下列内容: php_value include_path /path/to/lib ZendZend类包含了一些经常使用的静态方法的集合。下面是唯一一个你要手工添加的类: 一旦你包含了Zend.php,你就已经包含了Zend类的所有的类方法。用loadClass()就可以简单地加载其它类。例如,加载Zend_Controller_Front类: include_path能理解loadclass()及ZF的组织和目录结构。我用它加载所有其它类。Zend_Controller使用这个controller非常直观。事实上,我写本教程时并没有用到它丰富的文档。 提示:文档目前已经可以在/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_ViewZend_View是一个用来帮助你组织好你的view逻辑的类。这对于模板-系统是不可知的,为了简单起见,本教程不使用模板。如果你喜欢的话,不妨用一下。 记住,现在所有的访问都是由front controller进行处理。因此应用框架已经存在了,另外也必须遵守它。为了展示Zend_View的一个基本应用,将IndexController.php修改如下: setScriptPath(/path/to/views);echo$view-render(example.php);publicfunctionnoRouteAction()$this-_redirect(/);?在views目录创建example.php文件: ThisIsanExampleThisisanexample.现在,如果你访问自己网站的根资源,你会看到example.php的内容。这仍没什么用,但你要清楚你要在以一种结构和组织非常清楚的方式在开发网络应用。 为了让Zend_View的应用更清楚一点,修改你的模板(example.php)包含以下内容: escape($this-title);?escape($this-body);?现在已经添加了两个功能。$this-escape()类方法用于所有的输出。即使你自己创建输出,就像这个例子一样。避开所有输出也是一个很好的习惯,它可以在默认情况下帮助你防止跨站脚本攻击(XSS)。 $this-title和$this-body属性用来展示动态数据。这些也可以在controller中定义,所以我们修改IndexController.php以指定它们: setScriptPath(/path/to/views);$view-title=DynamicTitle;$view-body=Thisisadynamicbody.;echo$view-render(example.php);publicfunctionnoRouteAction()$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()来获取$_POSTname中的字母: 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(/);functioncommentAction()/*Addacomment.*/functionnewsAction()/*Addnews.*/function_call($action,$arguments)$this-_redirect(/);?记住AddController的indexAction()方法不能调用。当访问/add时会执行这个类方法。因为用户可以手工访问这个网址,这是有可能的,所以你要把用户重定向到主页、显示错误或你认为合适的行为。 接下来,创建AdminController.php文件: _redirect(/);?最后,创建ViewController.php文件: _redirect(/);function_call($id,$arguments)/*Displaynewsandcommentsfor$id.*/?和AddController一样,index()方法不能调用,所以你可以使用你认为合适的action。ViewController和其它的有点不同,因为你不知道什么才是有效的action。为了支持像/view/23这样的网址,你要使用_call()来支持动态action。 数据库操作因为Zend Framework的数据库组件还不稳定,而我希望这个演示可以做得简单一点。我使用了一个简单的类,用SQLite进行新闻条目和评论的存储和查询。 _db=newSQLiteDatabase($filename);publicfunctionaddComment($name,$comment,$newsId)$name=sqlite_escape_string($name);$comment=sqlite_escape_string($comment);$newsId=sqlite_escape_string($newsId);$sql=INSERTINTOcomments(name,comment,newsId)VALUES($name,$comment,$newsId);return$this-_db-query($sql);publicfunctionaddNews($title,$content)$title=sqlite_escape_string($title);$content=sqlite_escape_string($content);$sql=INSERTINTOnews(title,content)VALUES($title,$content);return$this-_db-query($sql);publicfunctionapproveNews($ids)foreach($idsas$id)$id=sqlite_escape_string($id);$sql=UPDATEnewsSETapproval=TWHEREid=$id;if(!$this-_db-query($sql)returnFALSE;returnTRUE;publicfunctiongetComments($newsId)$newsId=sqlite_escape_string($newsId);$sql=SELECTname,commentFROMcommentsWHEREnewsId=$newsId;if($result=$this-_db-query($sql)return$result-fetchAll();returnFALSE;publicfunctiongetNews($id=ALL)$id=sqlite_escape_string($id);switch($id)caseALL:$sql=SELECTid,titleFROMnewsWHEREapproval=T;break;caseNEW:$sql=SELECT*FROMnewsWHEREapproval!=T;break;default:$sql=SELECT*FROMnewsWHEREid=$id;break;if($result=$this-_db-query($sql)if($result-numRows()!=1)return$result-fetchAll();elsereturn$result-fetch();returnFALSE;?(你可以用自己的解决方案随意替换这个类。这里只是为你提供一个完整示例的介绍,并非建议要这么实现。) 这个类的构造器需要SQLite数据库的完整路径和文件名,你必须自己进行创建。 query(CREATETABLEnews(idINTEGERPRIMARYKEY,titleVARCHAR(255),contentTEXT,approvalCHAR(1)DEFAULTF);$db-query(CREATETABLEcomments(idINTEGERPRIMARYKEY,nameVARCHAR(255),commentTEXT,newsIdINTEGER);?你只需要做一次,以后直接给出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视图: NewsNewsnewsas$entry)?ahref=/view/escape($entryid);?escape($entrytitle);?AddNewsTitle:Content:view.php模板可以用来显示选定的新闻条目: escape($this-newstitle);?escape($this-newstitle);?escape($this-newscontent);?Commentscommentsas$comment)?escape($commentname);?writes:escape($commentcomment);?AddaCommentinputtype=hiddenname=newsIdvalue=escape($this-id);?/Name:Comment:最后,admin.php模板可以用来批准新闻条目: NewsAdminnewsas$entry)?inputtype=checkboxname=idsvalue=escape($entryid);?/escape($entrytitle);?escape($entrycontent);?Password:提示:为了保持简单,这个表单用密码作为验证机制。使用到模板的地方,你只需要把注释替换成几行代码。如IndexController.php就变成下面这样: news=$db-getNews();echo$view-render(index.php);publicfunctionnoRouteAction()$this-_redirect(/);?因为条理比较清楚,这个程序首页的整个业务逻辑只有四行代码。AddController.php更复杂一点,它需要更多的代码: _redirect(/);functioncommentAction()/*Addacomment.*/$filterPost=newZend_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);functionnewsAction()/*Addnews.*/$filterPost=newZend_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);functionapproveAc

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论