[学习笔记] symfony核心类 [转]

symfony核心类 Symfony Core Classes

在本书里你会经常碰到symfony的MVC核心的几个类:

  • sfController 控制器类。它解析请求并交给动作处理。
  • sfRequest 保存所有的请求元素(参数,cookie,请求的头 等)。
  • sfResponse 包含回应的头和内容。它的内容最终会转化为HTML传给用户。
  • context singleton (由sfContext::getInstance()取得) 保存所有核心对象还有当前的配置的引用,它可以从任何地方访问到。

在第6章你会了解到更多这些对象的信息。

如你所见,所有的symfon类都有一个sf前缀,很多symfony模版中的核心变量也是这样。这样可以避免与你的类名与变量名重复,并使框架核心类更像是一家人,更好辨认。

symfony的编码规范中,开头字母大写的驼峰字(UpperCamelCase)是变量名与类名的标准。只有两个例外:核心symfony类以小写的sf开头,模版里面的变量使用小写下划线的方式。

代码组织 Code Organization

现在你了解了symfony应用程序的不同组成部分,你可能会想知道它们是怎么组织的。symfon按照项目组织代码,项目文件放在标准的树结构里。

项目结构: 应用程序,模块与动作 Project Structure: Applications, Modules, and Actions

一个symfony项目由一个域名下的服务与操作组成,它们共享同样的对象模型。

在一个项目里,操作逻辑上组成应用程序。同一个项目里面的不同应用程序相互独立。大多数情况,一个项目会包含两个应用程序:一个是前台,一个后台,它们共享同一个数据库。不过一个项目也可以包含很多小网站,每一个站点是一个不同的应用程序。注意应用程序间的链接必须用绝对形式。

每个应用程序由一个或更多模块组成。模块就是功能相近的一个页面或者一组页面。例如,模块 home ,articles, helpshoppingCartaccount 等。

模块包含动作,也就是说一个模块可以包含多个动作。例如,shoppingCart模块也许会有add,showupdate`等动作。一般来说,动作的名字是动词。动作就好像一般的web应用程序的页面一样,尽管两个动作可能显示同样的页面(例如,在给文章留言后还会把文章显示出来)。

如果你认为这么做对于一个刚开始的项目来说层次太多了,你可以很方便的把所有的动作集中到一个模块里,这样文件结构就简单了。当应用程序越来越复杂,你就需要把这些动作分开放到不同的模块。本书第1章提到,通过重写代码来改善结构与可读性(同样保留功能)被称为重构,当你应用RAD原则的时候经常需要这么做。

图 2-3 是一个blog项目的代码组织结构图,按照项目/应用程序/模块/动作来划分。 但注意项目的实际文件结构可能会与图里面的不一样。

图 2-3 - 代码组织结构例子

代码组织结构例子

目录结构

所有的web项目都有这些内容:

  • 一个数据库,例如MySQL或者PostgreSQL
  • 静态文件(HTML, 图片, JavaScript文件,样式表等)
  • 网站管理员与用户上传的文件
  • PHP类与函数库
  • 外部库(第三方脚本)
  • 批处理文件 (用于命令行或者cron的脚本)
  • 日志文件 (应用程序或者服务器的留下的脚印)
  • 配置文件

symfony用一种合理的目录结构组织所有这些内容,这种树形结与symfony的架构(MVC模式与应用程序/项目/模块分组)想符合。这个目录结构是在项目,应用程序,模块初始化的时候自动生成的。当然,为了满足客户的需求你可以完全自定义这个结构。

根目录结构

这些是一个symfony项目根目录下的文件:

apps/ frontend/ backend/ batch/ cache/ config/ data/ sql/ doc/ lib/ model/ log/ plugins/ test/ unit/ functional/ web/ css/ images/ js/ uploads/

表 2-1 介绍这些目录的内容

表 2-1 - 根目录

目录描述
apps/ 包含此项目内所有应用程序(一般情况, frontend 与 backend 分别代表前台与后台).
batch/ 包含命令行下运行的PHP脚本或者定期执行的脚本
cache/ 包含了配置文件的缓存,如果你开了动作和模版,还有这两个部分的缓存。缓存机制(详见第12章)把这些信息存在文件里面加快响应web请求的速度。每个应用程序都会有一个子目录,包含了预处理的PHP与HTML文件。
config/ 存放项目的配置信息。
data/ 这里是你可以存放项目的数据文件,例如数据库schema,包含了建立数据表的SQL文件,或者一个SQLite数据库文件。
doc/ 存放项目文档,包括你自己的文档和PHPdoc生成的文档。
lib/ 主要用来存放外部类或者库。这里的内容整个项目都能访问到。'model/`子目录存放项目的对象模型(详见第8章)。
log/ 存放symfony生成的应用程序的日志文件。也可以放web服务器的日志文件,数据库日志文件,或者项目的任何地方的日志文件。symfony自动为项目的每一个应用程序的每一个环境生成一个日志文件(l日志文件详见第16章).
plugins/ 存放安装在项目里的插件(插件详见第17章)。
test/ 包含PHP写的与symfony测试框架兼容的单元与功能测试(详见第15章)。 项目初始化的时候,symfony会自动建立一些基本的测试。
web/ web服务器的根目录。所有从因特网能够直接访问的文件都在这个目录里。

应用程序目录结构 Application Tree Structure

所有应用程序的目录结构都是一样的:

apps/ [应用程序名]/ config/ i18n/ lib/ modules/ templates/ layout.php error.php error.txt

表 2-2 介绍应用程序的子目录

表 2-2 - 应用程序的子目录

目录描述
config/ 包含一些YAML格式的配置文件。大部分应用程序的配置信息都在这里,symfony框架自己的默认配置除外。 注意需要的话默认值可以修改。详见第5章。
i18n/ 包含应用程序的国际化文件--大部分的界面翻译文件(详见第13章)。如果你用数据库存放翻译信息可以忽略这个目录。
lib/ 包含应用程序用到的类与库。
modules/ 存放应用程序的所有功能模块。
templates/ 包含应用程序的全局模版--所有模块公用的模版。默认情况,这个目录会有一个layout.php文件,这是模块模版默认主布局。

新应用程序的i18n/lib/, 与 modules/ 目录是空的。

一个应用程序的类的方法或属性不能被同一个项目的其他应用程序访问到。另外,同一项目的两个应用程序之间的超链接必须用绝对形式。开始把项目分成不同的应用程序的时候,这个这个限制就存在了。

模块目录结构 Module Tree Structure

每个应用程序包括一个或更多的模块。在modules每个模块都有它自己的子目录,这个目录的名字是模块初始化的时候确定的。

这是一个典型的模块目录结构:

apps/ [应用程序名]/ modules/ [模块名]/ actions/ actions.class.php config/ lib/ templates/ indexSuccess.php validate/

表 2-3 介绍模块子目录

表 2-3 - 模块子目录

目录描述
actions/ 一般只有一个文件actions.class.php,这个文件里面包含了模块的所有动作。模块的不同动作也可以分开写在不同的文件里。
config/ 可以存放与模块的配置信息。
lib/ 存放模块的类与库。
templates/ 存放模块里所有动作的模版。模块初始化的时候,会建立一个默认模版indexSuccess.php
validate/ 用户存放表单验证配置信息(详见第10章)。

新模块的config/lib/, 与validate/ 目录是空的

web目录结构

web目录的限制很少,这里存放的是互联网可以访问得到的文件。模版的默认行为还有helper里包含了几个基本的命名规则。下面是一个web目录的结构的例子:

web/ css/ images/ js/ uploads/

表 2-4 介绍web目录的内容

表 2-4 - 典型的web目录的子目录

目录描述
css/ 存放.css结尾的样式表文件
images/ 存放.jpg,.png.gif扩展名的图片文件。
js/ 存放.js扩展名的JavaScript文件
uploads/ 只能存放用户上传的文件。虽然这个目录通常会存放图片我们还是把这个目录与图片目录分开,这样同步开发服务器与正式服务器的时候不会影响上传的文件。

虽然强烈建议维持默认的目录结构,你还是可以作出修改,例如一个项目要运行在不同的目录结构与命名规则的服务器上。修改目录结构详见第19章。

常用工具 Common Instruments

有些技巧在symfony里面很常用,在项目中你会经常碰到他们。这包括参数holder,常量,还有类自动加载。

参数 holder Parameter Holders

很多symfony类都包含一个参数holder。参数holder用简便的方式封装了getter与setter方法。例如,sfResponse类包含了一个可以通过执行getParameterHolder()方法获得的参数holder。每一个参数holder都用同样的方式存取数据,如例2-15所示。

例 2-15 - 使用 sfResponse 参数holder

$response->getParameterHolder()->set('foo''bar')echo $response->getParameterHolder()->get('foo'); => 'bar'

大部分类通过使用参数holder的proxy方法来减少get/set操作的代码量。这是sfResponse对象的例子,例2-16可以达到例2-15同样效果。

Listing 2-16 - Using the sfResponse Parameter Holder Proxy Methods

$response->setParameter('foo''bar')echo $response->getParameter('foo'); => 'bar'

参数holder的getter方法可以有第二个参数作为默认值。这样在取值失败的时候比较简洁。见例2-17。

例 2-17 - 使用参数holder的get方法的默认值

// 'foobar' 参数没有定义, 所以getter返回空值 echo $response->getParameter('foobar'); => null   // 利用条件判断给一个默认值 if ($response->hasParameter('foobar')) { echo $response->getParameter('foobar')} else { echo 'default'} => default   // 但是使用第二个默认值参数快的多echo $response->getParameter('foobar''default'); => default

参数holder还支持命名空间。如果你给setter或者getter指定第三个参数,这个参数代表命名空间,那么这个参数就只会在这个命名空间里定义或者取值。见例2-18

例 2-18 - sfResponse 参数 Holder 的命名空间

$response->setParameter('foo''bar1')$response->setParameter('foo''bar2''my/name/space');echo $response->getParameter('foo'); => 'bar1' echo $response->getParameter('foo'null,'my/name/space'); => 'bar2'

当然,你可以给你自己的类增加参数holder来获得这些好处。例2-19告诉我们如何定一个有参数holder的类。

例 2-19 - 给类增加参数holder

class MyClass { protected $parameter_holder = null;   public function initialize ($parameters =array()) { $this->parameter_holder = new sfParameterHolder()$this->parameter_holder->add($parameters)}   public function getParameterHolder() { return $this->parameter_holder} }

常量 Constants

symfony里的常量少得出奇。这是因为PHP的一大缺点:常量定义后就不能改变了。所以symfony使用自己的配置对象,称作sfConfig,用来取代常量。它提供了在任何地方存取参数的静态方法。例2-20演示了sfConfig类的方法。

例 2-20 - 使用 sfConfig 类方法取代常量

// PHP常量 define('SF_FOO''bar')echo SF_FOO; // symfony 使用sfConfig对象sfConfig::set('sf_foo''bar')echo sfConfig::get('sf_foo');

sfConfig方法支持默认值,并且sfConfig::set()方法可以多次调用来设置同一个参数的值。第5章详细讨论了sfConfig方法。

类自动载入 Class Autoloading

一般来说,当你在PHP中要用一个类来创建一个对象的时候,你需要首先包含这个类的定义。

include 'classes/MyClass.php'$myObject = new MyClass();

但是大的项目包含了很深的目录结构,包含所有这些文件还有路径很浪费时间。由于有__autoload()函数(或者spl_autoload_register()函数),symfony使得我们不需要写包含语句,你可以直接这么写:

$myObject = new MyClass();

symfony会在项目的lib目录里的所有php文件里寻找MyClass的定义。如果找到,就自动包含它。

所以你可以把所有的类放在lib目录,你再也不必包含他们。所以symfony项目通常没有include或者require语句。

为了提高效率,第一次symfony自动在一个目录列表(在配置文件里面定义)里寻找。然后symfony把这些目录里的所有类和文件的关联存放在一个PHP数组里。这样,以后的自动载入就不需要扫描整个目录了。所以你每次在项目里面增加一个类都需要通过symfony clear-cache命令清空symfony缓存。缓存详见第12章,自动载入配置文件详见第19章。

总结

使用MVC框架迫使你按照框架的规定把代码分开。显示的代码归到视图里,数据处理的代码归到模型,请求处理逻辑归到控制器。这对MVC模式的应用程序很有用,也是一个约束。

symfony是一个PHP5写的MVC框架。它的结构充分发挥了MVC模式的好处,但也非常容易使用。这要感谢他的全面性与可配置性。

现在你已经了解了symfony背后的原理,差不多该是开发你的第一个应用程序的时候了。但是在这之前,你需要在你的开发服务器上安装一套symfony并跑起来。

posted on 2014-03-03 11:54 Felixdh 阅读(...) 评论(...) 编辑 收藏

导航

公告

统计