乍一看,symfony-driven应用程序背后的代码看上去令人生畏。ob娱乐下载它由许多目录和脚本,和文件的PHP类,HTML,甚至两者的混合物。您还将看到引用类否则应用程序文件夹内无处可寻,和目录深度延伸到6的水平。但是一旦你理解背后的原因的这种表面上的复杂性,你会突然觉得这是很自然的事情,你不会为任何其他贸易symfony应用程序结构。ob娱乐下载本章解释了,害怕的感觉。
ob娱乐下载Symfony是基于经典的web设计模式称为MVC架构,它包括三个层次:
图2 - 1展示了MVC模式。
MVC架构将业务逻辑(模型)和表示(视图),导致更大的可维护性。例如,如果您的应用程序应该运行在标准web浏览器和手持设备,你只需要一个新的视图;你可以保持原来的控制器和模型。控制器有助于隐藏的细节请求使用的协议(HTTP、控制台模式、邮件等等)的模型和视图。和抽象的逻辑数据模型,使独立的观点和行动,例如,数据库使用的应用程序的类型。
图2 - 1 - MVC模式
帮助您了解MVC的优势,让我们看看如何将一个基本的PHP应用程序转换为一个MVC-architectured应用程序。的帖子列表weblog应用程序将是一个完美的例子。
在一个平坦的PHP文件,显示数据库条目的列表的样子展示的脚本如清单2所示。
清单2 -一个平坦的脚本
< ? php/ /连接,选择数据库美元的链接=首先(“localhost”,“myuser”,“我的密码”);mysql_select_db(“blog_db”,美元的链接);/ /执行SQL查询美元的结果=mysql_query(“选择日期,从文章标题”,美元的链接);吗?>< html > <头> <标题>文章列表< /名称> < /头> <身体> < h1 >文章列表< / h1 > <表> < tr > < th >日期< / th > < th >标题< / th > < / tr >< ? php/ /打印结果在HTML中而(行美元=mysql_fetch_array(美元的结果,MYSQL_ASSOC)){回声”\ t< tr >\ n”;printf(”\ t\ t< td > % s < / td >\ n”,行美元(“日期”]);printf(”\ t\ t< td > % s < / td >\ n”,行美元(“标题”]);回声”\ t< / tr >\ n”;}吗?>< /表> < /身体> < / html >< ? php/ /关闭连接mysql_close(美元的链接);吗?>
快速的写,快速执行,无法维持。以下是这段代码的主要问题:
的回声和printf调用清单2 - 1使代码难以阅读。修改HTML代码来增强演讲是一个麻烦与当前语法。这样的代码可以分为两个部分。首先,纯PHP代码的业务逻辑控制器脚本,如清单2所示。
回声
printf
清单2 -控制器部分index . php
index . php
< ? php/ /连接,选择数据库美元的链接=首先(“localhost”,“myuser”,“我的密码”);mysql_select_db(“blog_db”,美元的链接);/ /执行SQL查询美元的结果=mysql_query(“选择日期,从文章标题”,美元的链接);/ /填充该数组的观点美元的帖子=数组();而(行美元=mysql_fetch_array(美元的结果,MYSQL_ASSOC)){美元的帖子(]=行美元;}/ /关闭连接mysql_close(美元的链接);/ /需要的观点需要(“view.php”);
PHP的HTML代码,包含模板语法,存储在一个视图脚本,如清单2所示。
清单2 - 3 -视图部分view.php
view.php
< html > <头> <标题>文章列表< /名称> < /头> <身体> < h1 >文章列表< / h1 > <表> < tr > < th >日期< / th > < th >标题< / th > < / tr >< ? phpforeach(美元的帖子作为美元的帖子):吗?>< tr > < td > < ? php回声美元的帖子(“日期”]? > < / td > < td > < ? php回声美元的帖子(“标题”]? > < / td > < / tr >< ? phpendforeach;吗?>< /表> < /身体> < / html >
一个好的经验法则来确定视图足够干净是它应该只包含一个最少的PHP代码,为了理解一个HTML设计师没有PHP知识。最常见的报表视图回声,如果/ endif,foreach / endforeach,这是所有。同样,不应当有PHP代码呼应HTML标记。
如果/ endif
foreach / endforeach
所有的逻辑都是搬到控制器脚本,和只包含纯PHP代码,没有HTML内。作为一个事实,你应该假设相同的控制器可以重用一个完全不同的表现,也许在一个PDF文件或XML结构。
大部分的控制器脚本代码致力于数据操作。但是,如果你需要另一个控制器的文章列表,说一个,输出RSS提要的博客帖子?如果你想要保持在一个地方所有的数据库查询,以避免代码重复?如果你决定改变的数据模型,这样帖子表被重命名weblog_post吗?如果你想切换到PostgreSQL代替MySQL呢?为了使这一切成为可能,您需要删除插入的代码从控制器并把它放到另一个脚本,叫做模型,如清单2 - 4所示。
帖子
weblog_post
清单2 - 4 -模型部分model.php
model.php
< ? php函数getAllPosts(){/ /连接,选择数据库美元的链接=首先(“localhost”,“myuser”,“我的密码”);mysql_select_db(“blog_db”,美元的链接);/ /执行SQL查询美元的结果=mysql_query(“选择日期,从文章标题”,美元的链接);/ /填充该数组美元的帖子=数组();而(行美元=mysql_fetch_array(美元的结果,MYSQL_ASSOC)){美元的帖子(]=行美元;}/ /关闭连接mysql_close(美元的链接);返回美元的帖子;}
修改后的控制器如清单2 - 5所示。
清单2 - 5 -控制器部分,修正index . php
< ? php/ /需要模型require_once(“model.php”);/ /检索文章的列表美元的帖子= getAllPosts();/ /需要的观点需要(“view.php”);
控制器变得更容易阅读。它的唯一任务是获得来自模型的数据并将其传递给视图。在更复杂的应用程序中,控制器也处理请求,用户会话,认证,等等。使用显式模型的函数的名称甚至使代码注释中不必要的控制器。
致力于数据访问模型脚本,可以相应的组织。所有参数不依赖于数据层(如请求参数)必须由控制器,而不是直接访问模型。模型的功能可以很容易地重用在另一个控制器。
MVC架构的原则是把代码分成三层,根据其性质。数据逻辑代码放置在模型,演示代码中的视图和控制器内的应用程序逻辑。
其他额外的设计模式可以使编码经验更容易。模型、视图和控制器层可以进一步细分。
模型层可以分为数据访问层和数据库抽象层。这样,数据访问功能不会使用database-dependent查询语句,但调用其他函数,将查询本身。如果你改变数据库系统之后,只需要更新的数据库抽象层。
给出了一个示例数据库抽象层在清单2 - 6中,紧随其后的是一个mysql数据访问层在清单2胜7负。
清单2 - 6 -数据库抽象模型的一部分
< ? php函数open_connection(美元的主机,$ user,美元的密码){返回首先(美元的主机,$ user,美元的密码);}函数close_connection(美元的链接){mysql_close(美元的链接);}函数query_database(美元的查询,美元的数据库,美元的链接){mysql_select_db(美元的数据库,美元的链接);返回mysql_query(美元的查询,美元的链接);}函数fetch_results(美元的结果){返回mysql_fetch_array(美元的结果,MYSQL_ASSOC);}
清单2 - 7日-数据访问模型的一部分
函数getAllPosts(){/ /连接数据库美元的链接= open_connection(“localhost”,“myuser”,“我的密码”);/ /执行SQL查询美元的结果= query_database(“选择日期,从文章标题”,“blog_db”,美元的链接);/ /填充该数组美元的帖子=数组();而(行美元= fetch_results(美元的结果)){美元的帖子(]=行美元;}/ /关闭连接close_connection(美元的链接);返回美元的帖子;}
您可以检查,没有数据库引擎依赖函数可以在数据访问层,使其数据库。此外,该函数中创建的数据库抽象层可以重用为许多其他模型函数,需要访问数据库。
请注意
清单2 - 6和2 - 7中的例子仍然不是很满意,还有一些工作要做一个完整的数据库抽象(抽象的SQL代码通过一个数据库查询构建器,将所有功能移动到一个类,等等)。但是这本书的目的不是向您展示如何编写所有的代码,在第8章,你会看到,symfony本地所有抽象得很好。ob娱乐下载
视图层也可以受益于一些代码分离。网页通常包含整个应用程序中一致的元素:页面标题、图形布局,页脚,和全球导航。只有内部页面的变化。这就是为什么视图分为布局和模板。布局通常是全球应用程序,或一组页面。模板只把形状变量可用的控制器。需要一些逻辑来让这些组件一起工作,和这个视图逻辑层将保持视图的名称。根据这些原则,清单2 - 3的视图部分可以分为三个部分,如清单2所示,2 - 9和2 - 10。
清单2 - 8 -模板视图的一部分,mytemplate.php
mytemplate.php
<标题>文章列表< / h1 > <表> < tr > < th >日期< / th > < th >标题< / th > < / tr >< ? phpforeach(美元的帖子作为美元的帖子):吗?>< tr > < td > < ? php回声美元的帖子(“日期”]? > < / td > < td > < ? php回声美元的帖子(“标题”]? > < / td > < / tr >< ? phpendforeach;吗?>< /表>
清单2 - 9 -视图逻辑视图的一部分
< ? php美元的标题=“帖子列表”;美元的帖子= getAllPosts();
清单2 - 10 -布局视图的一部分
< html > <头> <标题> < ? php回声美元的标题? > < /名称> < /头> <身体>< ? php包括(“mytemplate.php”);吗?>< /身体> < / html >
控制器不做太多在上一个示例中,但在真正的web应用程序中,控制器有很多工作。这项工作的一个重要组成部分是常见的所有应用程序的控制器。常见的任务包括请求处理、安全处理,加载应用程序配置,和类似的家务。这就是为什么控制器通常分为前端控制器,为整个应用程序是独一无二的,和行为,它只包含控制器代码具体为一页。
前端控制器的最伟大的优点之一是,它为整个应用程序提供一个独特的切入点。如果你决定关闭访问应用程序,你将只需要编辑前端控制器脚本。在一个应用程序没有一个前端控制器,每个控制器需要关闭。
所有前面的例子使用过程式编程。现代语言的OOP功能使编程更加容易,因为对象可以封装逻辑,继承,并提供干净的命名约定。
实现MVC架构的语言不是面向对象提出了名称空间和代码重复问题,和整体的代码难以阅读。
面向对象允许开发人员来处理诸如视图对象、控制器对象,模型类,将前面的例子中的所有函数转换成方法。这是一个必须为MVC架构。
提示
如果你想了解更多关于设计模式为web应用程序在一个面向对象的背景下,读了马丁的企业应用架构模式(addison - wesley, ISBN: 0-32112-742-0)。Fowler的书中代码示例Java或c#,但仍然非常可读的PHP开发人员。
坚持一分钟。对单个页面清单在博客文章中,组件是需要多少?如图2 - 2所示,我们有以下部分:
七个脚本,一大堆的文件打开和修改每次创建一个新页面!然而,symfonob娱乐下载y会让事情简单。在最好的MVC架构,symfony实现它的方式使应用程序开发快速、无痛。ob娱乐下载
首先,前端控制器和布局是常见的所有操作在一个应用程序。你可以有多个控制器和布局,但你只需要一个。前端控制器是纯粹的MVC逻辑组件,和你永远不会需要编写一个,因为symfony会为您生成它。ob娱乐下载
另一个好消息是,模型层的类也自欧宝平台是合法的吗动生成,根据你的数据结构。这是ORM库的工作,提供了类的骨骼和代码生成。如果ORM发现外键约束或日期字段,它将提供特殊的accessor和mutator方法,将数据操作小菜一碟。和数据库抽象是完全看不见你,因为它是PHP数据对象处理。如果你决定改变你的数据库引擎在任何时候,你有0代码重构。你只需要改变一个配置参数。
最后,视图逻辑可以很容易地翻译成一个简单的配置文件,并且不需要编程。
图2 - 2,Symfonob娱乐下载y的工作流
这意味着文章的列表描述在我们的例子中仅需要三个文件在symfony工作,如清单2 - 11所示,12和13。ob娱乐下载
清单2 - 11 -列表行动,在myproject /应用程序/ myapp /模块/博客/动作/ actions.class.php
列表
myproject /应用程序/ myapp /模块/博客/动作/ actions.class.php
< ? php类weblogActions扩展sfActions{公共函数executeList(){这个美元- >的帖子= PostPeer::doSelect(新标准());}}
清单12 -列表的模板,myproject /应用程序/ / listSuccess.php myapp /模块/博客/模板
myproject /应用程序/ / listSuccess.php myapp /模块/博客/模板
< ? php槽(“标题”,“帖子列表”)吗?><标题>文章列表< / h1 > <表> < tr > < th >日期< / th > < th >标题< / th > < / tr >< ? phpforeach(美元的帖子作为美元的帖子):吗?>< tr > < td > < ? php回声美元的帖子- >获取当前日期()? > < / td > < td > < ? php回声美元的帖子- >getTitle()? > < / td > < / tr >< ? phpendforeach;吗?>< /表>
此外,您还需要定义一个布局,如清单13所示,但是多次被重用。
清单13 -布局,myproject /应用程序/ myapp /模板/ layout.php
myproject /应用程序/ myapp /模板/ layout.php
< html > <头> <标题> < ? php包括_slot(“标题”)? > < /名称> < /头> <身体>< ? php回声sf_content美元吗?>< /身体> < / html >
这就是你所需要的。这是所需的确切代码同一页面显示为平面脚本显示在清单2 - 1。其余(使所有组件一起工作)是由symfony。ob娱乐下载如果算上,你会发现创建的列表在symfony的MVC架构不需要更多的时间比写一个平面文件或编码。ob娱乐下载然而,它为您提供了巨大的优势,尤其是明确的代码组织,可重用性,灵活性,和更多的乐趣。奖金,XHTML一致性,调试功能,简单的配置,数据库抽象,聪明的URL路由、多个环境,更多的开发工具。
symfony的MVC实现使用多个类,你经常会遇到这ob娱乐下载本书:
sfController
sfRequest
sfResponse
sfContext: getInstance ()
在第六章中你将学习更多关于这些对象。
正如你所看到的,所有的symfony类使用ob娱乐下载科幻小说前缀,symfony的核心变量的模板ob娱乐下载。这应该避免使用自己的类和变量名称冲突,并使核心框架类善于交际,很容易辨认。
科幻小说
在symfony中使用的编码标准,UpperCamelCase是标准类ob娱乐下载和变量命名。两个例外存在:核心symfony类开始ob娱乐下载科幻小说小写,和变量模板中使用underscore-separated语法。
现在你知道的不同组件symfony应用程序中,您可能想知道他们是如何组织的。ob娱乐下载ob娱乐下载Symfony项目组织代码结构和将项目文件放入一个标准的树结构。
在syob娱乐下载mfony中,一个项目是一组可用的服务和操作在一个给定的域名,共享相同的对象模型。
在一个项目中,逻辑地分组成应用程序的操作。应用程序通常可以独立运行的其他应用程序相同的项目。在大多数情况下,一个项目将包含两个应用程序:一个用于前台和后台,共享相同的数据库。但是你也可以有一个项目包含许多迷你站点,每个站点的不同应用程序。注意,应用程序之间的超链接必须是绝对的形式。
每个应用程序是一组一个或多个模块。一个模块通常代表一个页面或一组页面类似的目的。例如,您可能有模块家,文章,帮助,shoppingCart,账户,等等。
家
文章
帮助
shoppingCart
账户
模块持有行为代表的各种行为可以通过一个模块。例如,一个shoppingCart模块可以有添加,显示,更新行动。一般来说,行动可以被描述为一个动词。处理页面处理的行为就像是在一个典型的web应用程序,虽然两个动作会导致相同的页面(例如,添加一个评论发布在博客将重新显示发布新的评论)。
添加
显示
更新
如果这是太多的水平开始项目,很容易将所有操作分组到一个单一的模块,这样可以保持简单的文件结构。当应用程序变得更为复杂,这将是时间行动组织成不同的模块。如第一章中所述,重写代码,以改善其结构或可读性(但保留其行为)叫做重构,和你会做很多应用RAD的原则。
图2 - 3显示了一个示例代码组织一个博客的项目,在项目/应用程序/模块/动作结构。但要意识到项目的实际文件树结构会不同于图中所示的设置。
图2 - 3 -代码组织的例子
所有web项目通常共享同一类型的内容,如以下:
ob娱乐下载Symfony提供了一个标准的文件树结构来组织这些内容逻辑的方式,符合架构的选择(MVC模式和项目/应用程序/模块分组)。这个树结构是初始化时自动创建的每个项目,应用程序,或模块。当然,你完全可以定制它,重新组织文件和目录在你方便的时候或以匹配您的客户的需求。
这些发现在symfony项目的根目录:ob娱乐下载
应用程序/前端/后端/缓存/ config /数据/ sql / doc / lib /模型/日志/插件/测试/引导/单元/功能/ web / css /图片/ js /上传/
表2 - 1描述了这些目录的内容。
表2 - 1,根目录
应用程序/
前端
后端
缓存/
配置/
数据/
文档/
lib /
模型/
日志/
插件/
测试/
web /
所有应用程序目录的树结构是一样的:
应用程序(应用程序名称)/ config / i18n / lib /模块/模板/ layout.php
表2 - 2描述了应用程序的子目录。
表2 - 2——应用程序目录
i18n /
模块/
模板/
layout.php
的i18n /,lib /,模块/为一个新的应用程序目录是空的。
应用程序的类不能访问其他应用程序中的方法或属性相同的项目。还要注意,相同项目的两个应用程序之间的超链接必须绝对的形式。你需要记住这最后一个约束在初始化期间,当你选择如何将项目划分为应用程序。
每个应用程序包含一个或多个模块。每个模块都有自己的子目录中模块目录,该目录的名称中选择设置。
模块
这是典型的树状结构的模块:
应用程序(应用程序名称)/模块/模块名称/行动/ actions.class。php配置/ lib /模板/ indexSuccess.php
表2 - 3描述了模块子目录。
表2 - 3 -模块子目录
行为/
actions.class.php
indexSuccess.php
的配置/,lib /目录不自动创建一个新模块,所以你需要手动创建它们如果需要
很少有约束的网络目录,这是公共可访问的目录文件。遵循一些基本的命名约定将模板提供默认行为和有用的快捷键。这里的一个例子网络目录结构:
网络
web / css /图片/ js /上传/
一般来说,静态文件分布在目录表2 - 4所示。
表2 - 4——典型的Web目录
css /
. css
图像/
jpg
. png
gif
js /
. js
上传/
即使它是强烈建议您保持默认的树结构,可以修改它为特定的需求,如运行在一个服务器上允许一个项目不同的树结构规则和编码惯例。更多信息请参考19章修改文件树结构。
在symfony重复使用一些技巧,你会经常见到他们在这本书中,在自己的项目中。ob娱乐下载这些参数包括持有人、常量和类半自动的。
许多symfony的hoob娱乐下载lder类包含一个参数。这是一个方便的方式来封装属性用干净的getter和setter方法。例如,sfRequest类包含一个参数持有人,您可以检索通过调用getParameterHolder ()方法。每个参数持有人以相同的方式存储数据,如清单2 - 14所示。
getParameterHolder ()
清单2 - 14 -使用的sfRequest参数持有人
美元的请求- >getParameterHolder()- >集(“foo”,“酒吧”);回声美元的请求- >getParameterHolder()- >得到(“foo”);= >“酒吧”
大部分的类使用一个参数持有人提供代理方法来缩短获取/设置操作所需的代码。是这样的sfRequest对象,所以你可以做同样的如清单2 - 14所示的代码清单男童。
清单男童——使用sfRequest参数持有人代理方法
美元的请求- >setParameter(“foo”,“酒吧”);回声美元的请求- >getParameter(“foo”);= >“酒吧”
参数持有人getter接受默认值作为第二个参数。这提供了一个有用的回退机制比可能更简洁的条件语句。请参见清单- 18为例。
清单- 18 -使用持有人Getter属性的默认值
/ /“foobar”参数是没有定义的,所以getter返回一个空值回声美元的请求- >getParameter(“foobar”);= >零/ /默认值可以通过将使用getter的条件如果(美元的请求- >hasParameter(“foobar”)){回声美元的请求- >getParameter(“foobar”);}其他的{回声“默认”;}= >默认的/ /但更快的使用第二个getter的论点回声美元的请求- >getParameter(“foobar”,“默认”);= >默认的
一些symob娱乐下载fony核心类还使用一个参数架,支持名称空间(多亏了sfNamespacedParameterHolder类)。如果你指定一个setter和getter第三个参数,它被用作一个名称空间,只定义的参数将在这个名称空间。清单2-17显示了一个示例。
sfNamespacedParameterHolder
清单2-17——使用sfUser参数持有人名称空间
sfUser
$ user- >setAttribute(“foo”,“bar1”);$ user- >setAttribute(“foo”,“bar2”,“我的/名称/空间”);回声$ user- >getAttribute(“foo”);= >“bar1”回声$ user- >getAttribute(“foo”,零,“我的/名称/空间”);= >“bar2”
当然,您可以添加一个参数夹自己的类,以利用他们的语法设施。清单最近展示了如何用一个参数定义一个类。
清单最近- Holder类添加一个参数
类MyClass{受保护的parameterHolder美元=零;公共函数初始化(美元的参数=数组()){这个美元- >parameterHolder=新sfParameterHolder();这个美元- >parameterHolder- >添加(美元的参数);}公共函数getParameterHolder(){返回这个美元- >parameterHolder;}}
你不会找到任何常数symfony,因为你不能改变他们的本质价值,一旦他ob娱乐下载们被定义。ob娱乐下载Symfony使用自己的配置对象,调用sfConfig,代替常量。它提供了静态方法访问参数来自世界各地。三分之一的清单演示了使用sfConfig类方法。
sfConfig
三分之一的清单——使用sfConfig类方法而不是常数
/ /而不是PHP常数,定义(“FOO”,“酒吧”);回声FOO;/ /ob娱乐下载 symfony使用sfConfig对象sfConfig::集(“foo”,“酒吧”);回声sfConfig::得到(“foo”);
sfConfig方法支持默认值,您可以调用sfConfig::设置()方法不止一次在同一参数来改变它的值。第五章讨论了sfConfig更详细的方法。
sfConfig::设置()
通常,当你使用一个类方法或用PHP创建一个对象,你首先需要包含类定义:
include_once“类/ MyClass.php”;myObject美元=新MyClass();
与许多大型项目类和深目录结构,跟踪所有类文件包括及其路径可以耗费时间。通过提供一个spl_autoload_register ()函数,symfonyob娱乐下载会让include_once不必要的语句,你可以直接写:
spl_autoload_register ()
include_once
myObject美元=新MyClass();
ob娱乐下载Symfony将寻找一个MyClass定义在所有文件结束class.php在一个项目的lib /目录。如果找到类定义,它将自动被包括。
MyClass
class.php
所以如果你储存你所有的类lib /目录,您不需要包含类了。这就是为什么symfoob娱乐下载ny项目通常不包含任何include_once或require_once语句。
require_once
更好的性能,symfony自动装卸机扫描目录列表(内部配ob娱乐下载置文件中定义)在第一次请求。然后注册这些目录包含的所有类和存储类/文件对应一个PHP文件作为一个关联数组中。这样,未来的请求不需要做目录扫描了。这就是为什么你需要清除缓存每次添加或移动在您的项目通过调用一个类文件ob娱乐下载symfony缓存:清晰命令(除了在开发环境中,symfony清空缓存时,无法找到一个类)。ob娱乐下载你会了解更多关于第12章的缓存,在19章和半自动的配置。
ob娱乐下载symfony缓存:清晰
使用MVC框架迫使你划分和组织你的代码框架的惯例。表示代码视图,数据操作的代码模型,和请求处理逻辑控制器。这使得应用MVC模式都非常有用,同时也很严格。
ob娱乐下载用PHP编写的Symfony是一个MVC框架。它的结构是为了得到最好的MVC模式,同时保持巨大的易用性。由于它的多功能性和可配置性,symfony适合所有web应用程序项目。ob娱乐下载
现在你理解symfony背后潜在的理论,您几乎准备好开发您的第一个应用程序。ob娱乐下载但在此之前,你需要一个symfony开发服务器上安装并运ob娱乐下载行。
这项工作是GFDL许可执照。