序
1,读者
这份手册是为了那些想快速建立web程序的人所写。CakePHP是为了帮助PHP各个层次用户简单快速的创建健壮、可维护的程序
这份手册需要一些PHP和HTML的基础知识,对MVC编程模式的一些了解。
2,CakePHP是免费的
遵循MIT License,主页http://www.cakephp.org
3,社区
第一章 CakePHP介绍
1,什么是CakePHP
CakePHP是一个开元的PHP的快速开发框架
2,为什么用CakePHP
CakePHP拥有一些快速开发的特征
1,兼容PHP4和PHP5
2,提供整合的数据库交互CRUD和简单的查询(包括 scaffolding)
3,Request dispatcher(原文Request dispatcher with good looking, custom URLs)
4,快速可变的模版(使用helpers的PHP语法)
5,许多有用的核心特征(access control lists以及AJAX整合等等)
6,在任何网站子目录下面都正常工作,很少需要Apache的配置(原文Works from any website subdirectory, with little to no Apache configuration involved)
3,CakePHP的历史
2005年,Michal Tatarynowicz用PHP写了一个快速开发的框架并发现这是一个好的框架的开始,于是Michal Tatarynowicz在MIT License下公布了这个框架并命名为Cake,并向开发者社区公布,后者现在维护项目并命名为CakePHP
第二章 基本概念
1 MVC模式
为了更好的理解类似Cake的web程序,你需要了解一些 Ruby on Rails这个框架,Cake的灵感就来自于Ruby on Rails。Ruby on Rails是编程语言Ruby的网站开发框架。它实现了Active Record和MVC模式。文章 What goes Where?详细解释了Rails的结构,Cake也使用了类似的结构。
Model View Controller是Gang of Four描述的一个软件的设计模式,Dean Helman介绍:“MVC模式,将一个项目,甚至是一个接口分成三个部分:model,view和controller。开发MVC是为了将传统的输入,处理,输出映射到GUI领域
Input -> Processing -> Output
Controller -> Model -> View
用户输入,外部世界的模型和显示用户的输出被model,view port和controller objects所操作。controller将用户的鼠标、键盘操作解释并映射到对应的命令,然后发送给model或者view并影响相应的变化。model管理一个或若干数据元素,根据状态的查询、变化状态的操作做对应的响应。view port管理一个矩形的显示,并通过图形和文字的结合对给用户准备好的数据作出响应(注:我认为就是显示出来)
关于MVC,你可以通过这个文章了解更多的机制 MVC: Most vexing conundrum
2,Cake的文件结构
当你解压缩安装包,你会发现四个文件夹app, cake, tmp 和vendors.其中cake文件夹是cake的核心库,基本上你不需要进行修改除非你需要对Cake进行一些定制
在
1,如果你有许多的web应用程序,你需要下载并安装Cake两次,这样核心库就重复了,这个是空间的一种浪费。并且违背了CakePHP试图遵循的DRY哲学原则
2,当CakePHP新的版本发布时,你必须非常小心的以免你的app文件夹下面的程序被默认的程序覆盖
app文件夹是你的程序和文件所在的地方。核心库文件夹cake和程序文件夹app的愤慨使得你可以有许多的程序,但只需要一份cake库,并且使得升级CakePHP变得更加容易:你只需要下崽最新版本的Cake并把你当前的核心库cake文件夹覆盖掉,而不需要旦夕覆盖掉你的app文件夹
tmp文件夹是用于存储cake操作的变量,比如baking,caching和logging
vendors文件夹用于存放第三方库文件,你需要在稍后更多的了解vendors
下面的列表显示了主要的文件夹和他们的基本目的
●cake(根目录)
○app(存放你的程序)
●config(配置文件,比如ACL,core, database connection,routes, paths, tags)
●controllers(放置controllers)
●(components,帮助你使用controller的类)
●index.php(cake中有三个该文件,方便用户用不同的方法配置cake)
●models(放置models)
●plugins(放置plugins或者第三方程序)
●views(view相关文件)
●elements(一些重复使用的较小的layout item)
●errors(错误文件)
●helpers(自定义的helpers文件)
●layouts(layout文件)
●pages(PagesController管理的静态内容)
●webroot(把这个目录设置成为网站根目录,并将public files放在这里)
●css
●files
●img
●js
○cake(库文件:最好不要修改)
○index.php
○tmp(用来放置logs,baking)
○vendors(粘贴第三方库文件)
第三章 安装CakePHP
1,Requirements
你必须有一个服务器,具备程序和库来运行CakePHP
1.1 服务器的要求
1.HTTP服务端(比如Apache),下面的选项要打开:sessions, mod_rewrite(虽然不是必须但是建议有)
2.PH
3.数据库引擎(现在已经支持MySQL,PostgreSQL and a wrapper for ADODB)
2.安装CakePHP
2.1 得到最新的稳定版本
www.cakephp.org 点击Downloads>Release
2.2 解压缩
放置到根目录,解压缩,有两种安装方式,开发方式安装使得你可以容易的在一个域名下面察看许多CakePHP程序,产品安装方式使得一个域名下面只有一个程序
3. 建立CakePHP
第一种方法在开发环境下比较合适,但是并不安全。第二种方法更安全可以安装在最终产品的环境下
3.1 开发方式安装
为了开发,我们可以将整个Cake的安装目录放到特殊的DocumentRoot下,如下:
这种安装wwwroot当作整个网站的目录,所以你的URL如下显示
如果你使用了mod_rewrite, 你的URLs会变成下面的这种形式
3.2 产品方式安装
为了实现产品方式的安装,你必须用于修改服务器上网站根目录的权限,修改根目录,使得整个域像只有一个CakePHP程序
安装后的程序结构如下
例3.1 建议的httpd.conf
在这种配置下,webroot就当作了网站的根目录,你的URL就可能像下面这样
如果你使用了mod_rewrite,你的URL就会类似于下面的
一些共享主机的用户可能没有权限通过修改http.conf来改变DocumnentRoot来指向他们的产品安装。在这种情况下,用户可以安装下面的方式,修改CakePHP的结构。Cake安装在 /path_to_cake_install,文件目录(不可以修改)指向/public_html
实际上,你将Cake的/app/webroot文件夹的内容拷贝到你已经存在的DocumentRoot。为了告诉Cake你的webroot文件在哪里,将下面几行田间到你DocumentRoot文件夹下面的index.php中(针对上面的例子就是/public_html/index.php)
4. 配置Apache和mod_rewrite
当CakePHP没有mod_rewrite支持时候,我们发现许多用户由于不能完美运行他们的系统而苦恼。下面是一些可能需要尝试并且使之正确运行的事情:
● 确定 .htaccess的override是允许的:在你的httpd.conf中,你需要有一段代码,在你的服务器上每个目录。确定AllowOverride对当前的目录设置成为All
● 确定你修改的是系统的httpd.conf,而不是用户或者特定站点的httpd.conf
● 在某些情况下,你可能得到一份缺少 .htaccess文件的CakePHP,这可能是因为某些系统把 .开头的文件当作隐藏文件就不拷贝。确定你拷贝的文件来中包含.htaccess
● 确定你正确上传mod_rewrite。你可以查看一下 httpd.conf中类似于LoadModule rewrite_module libexec/httpd/mod_rewrite.so 和AddModulemod_rewrite.c
5. 确定CakePHP正确工作
现在,我们实际查看一下。根据你选择不同的安装方式,你应该将你的浏览器的URL指向 http://www.example.com或者http://www.example.com/cake.这时,你会看到CakePHP的默认目录,以及一条数据库连接状态的消息。
恭喜!你现在已经可以创建你的第一个基于Cake的程序了。如果你现在什么都没有看到或者受到一条错误信息,可以到http://wiki.cakephp.org或者#cakephp on irc.freenode.net寻找更多的帮助。
第四章 配置
1. 数据库配置
app/config/database.php文件是数据库配置文件。默认安装后并没有database.php文件,所以你需要拷贝database.php.default到database.php. 之后,你可以看到如下:
例4.1
根据你的数据库连接信息替换上面的配置
CakePHP支持下面的数据库驱动
$default 连接中的connect key允许你设置是否需要持久连接数据库,请仔细阅读database.php.default文件中的注释,以配置你的数据库连接类型。
你的数据库中的表也应该遵循下面的命名规则:
● cake使用的表名(Table name)应该有英文的复数形式组成,比如users, authors, articles. 注意,对应的model是单数形式
● 所有的表 都必须有一个主键叫做 id
● 如果你需要关联tables,使用外键比如 article_id 。表的名字是单数,必须是小写,比如id
● 另外,最好遵从下面的命名规则以便更方便的使用某些功能
Include a ‘created’ 列
Include a ‘modified’列
你也可能注意到了database.php文件中有一个$test的连接,填上这个配置(或者添加其他类似的配置文件),在你使用的时候将下面的代码
添加到你的一个models中
2. 全局配置
CakePHP的全局配置可以在/app/config/core.php找到。尽管我们确实不喜欢配置文件,但是配置确实很难做。在这个文件中你可以修改一些,每一项设置都可以在core.php的注释中找到。
DEBUG: 设置这个变量不同的值可以帮助你在运行文件的时候debug你的程序。江这个值设成不同的非0值,可以使得Cake打印出SQL语句并且阻止程序下一步进行(原文:Specifiying this setting to a non-zero value will force Cake to print out SQL statements and stop flash messages from forwarding.)
CAKE_SESSION_COOKIE:在你的Cake应用中,这个变量可以设置成为保存用户session的cookie名字
CAKE_SECURITY:这个变量不同的值达标不同的sessions检查等级。Cake创建新的session,删除旧的session都基于这个变量。下面是可能的值:
high: session十分钟后失效
medium: session 二十分钟后失效
low: session 三十分钟后失效
CAKE_SESSION_SAVE: 设置如何保存session。下面是可能的值
cake: 保存在tmp/目录下
php: 根据php.ini中的设置保存
database: 被保存到默认(现在还没有实现,以后继续完善)
3.路径设置
‘Routing’是类似于mod_rewrite的 pared-down pure-PHP(机制),可以帮助将URL影射到 controller/action/params. Cake 添加这个可以帮助我们更好的实现URL转化并使得我们可以脱离mod_rewrite的要求。然而使用mod_rewrite,使得我们的address bar显得更加整洁。
Routes是映射URLs到特定的controllers和actions的独立规则。Routes被配置在app/config/routes.php文件中,设置形式如下:
例4.2 Route Pattern
在这里
URL是Cake的URL你想要映射的(URL is the Cake URL you wish to map)
controllername 是你想要调用的controller的名字
actionname 是你想要调用controller的action的名字
firstparam是特定的action的第一个参数
下面的这个例子将/blog下面的所有URL连接到了BlogController. 默认的action是BlogController::index()
例4.3 Route Example
一个URL 比如 /blog/history/05/june 处理如下:
例4.4 Route Handing in a Controller
URL中的’history’被匹配到 Blog route中的:action.( The 'history' from the URL was matched by :action from the Blog's route.) URL中被*匹配的元素被传递到活动的controller的处理方法,这里是$year和$month。比如这个URL /blog/history/05, 仅仅传递一个参数05给history()
接下来的例子是默认的CakePHP route,指向 PagesController::display(‘home’).其中home是一个view,位于/app/views/pages/home.thtml
例4.5 Setting the Default Route
第五章 Scaffolding (脚手架?)
Scaffolding是一个很棒的途径,使得早期开发的部分web应用能够运行起来。早期的数据库模式是不稳定的,很容易变化。Scaffolding有个下降趋势:web程序员憎恨创建以后可能根本用不到的forms。为了减少程序员的这种重复劳动, Cake中包含了Scaffolding。Scaffolding分析数据库,创建一些标准的使用add、delete、和edit按钮的lists,创建输入的forms,以及查看数据库中一个item的标准views。为了在程序中的controller中添加Scaffolding,需要添加$scaffold变量:
第六章 Models
本章内容:
1. Model Function
1.1 用户定义的Function
1.2 检索(retrieving)你的数据
1.3 保存你的数据
1.4 Model的回调(callbacks)
2. Model的变量
3. Associations
Model是什么,它是MVC模式中的M
Model做些什么。它使得domain logic和presentation分隔开,独立application logic(It separates domain logic from the presentation, isolating application logic.)
一个Model概要的说就是一个指向数据库的access,更具体,就是数据库中的特定的table。默认的,每个model都使用自身名字复数形式的table,比如,User Mode使用 users
table。Models可以维护数据特定的规则,联结信息以及它使用的table的方法。
1. Model的方法
从PHP的观点看,models都是从AppModel类继承来的类。类AppModel原始是定义在 /cake目录下。你也可以创建自己的放在 app/app_model.php.这个文件应该包含一些可供多个models共享的方法。AppModel本身也是从Model类继承而来的,Model类是一个标准的Cake库,定义在 libs/model.php
注意
虽然本节介绍的是Model中常用的方法,然而记住:更详细的参考请到http://api.cakephp.org
1.1 用户定义的方法
下面是model中一个特定table的例子,该例子实现了在blog中显示和隐藏两种方法
例6.1 Example Model Functions
1.2 检索数据
下面是使用model得到数据的一些标准方法
●findAll($conditions,$fields,$order,$limit,$page,$recursive)
○返回特定的fields,fields由$limit(默认是50)个记录,匹配$conditions(如果有),从第$page(默认1)页开始列表,$conditions内容应该像SQL语句中的一样,比如:$conditions=”race = ‘wookie’ AND thermal_detonators>
○当$recursive选项设置成1到3的整数,findAll()将会试图返回在联结到该model中发现的所有项的models.这项递归寻找可以深入3层。
●find($conditions, $fields, $order, $recursive)
○返回匹配$conditions的第一条记录的制定的fields(如果没有指定则返回全部)
○$recursive作用同上
●findAllBy<FieldName>($value) and findBy<FieldName>($value)
○这些奇妙的方法可以用于指定特定的field和特定的value快速查找行,你要做的就是把你的field用驼峰表达法添加在后面。举个例子(用于controller中)
返回的结果是一个数组,和find()以及findAll()返回的结果是一个形式
●field($name,$conditions,$order)
○根据$order排序,根据条件$conditions,将第一条记录中的field值,作为string返回
●findCount($conditions)
○返回匹配$conditions的记录的个数
●generateList
($conditions=null,$order=null,$limit=null,$keyPath=null,$valuePath=null)
●read($fields=null, $id=null)
○使用这个方法从当前装载的记录或者由$id指定的记录中得到fields和值
特定的Sql调用可以使用model的findBySql()方法。举例,在blog应用中,我想存储一个发贴者的first name到一个table中,但是这个table并不是我的cake schema中的一部分。我就可以通过这个model中的一个特定的方法
例6.2 Custom Sql Calls With findBySql()
当然也有query()方法,如果执行成功返回true,失败返回false。因为query语句并不是都返回结果集。比如“DELETE FROM problems WHERE solved = true”
1.3 保存数据
为了保存你的数据到model中,你应该向model提供你想要保存的数据。这些数据提交给save()方法应该以下面的形式保存
从form表单提交(post方法)的数据会自动排列成这种形式,并且放置到controller中的$this->params[‘data’],因此,通过web的form表单保存数据非常简单。一个controller的编辑方法可能会像下面这样显示:
注意save操作是如何放置在一个条件语句中:如果你试图保存数据到model中,cake自动尝试确数据正确(根据你提供的规则)。可以查看第十章了解更多关于正确规则(validation).如果不想查看正确性直接保存数据,使用save($data,false);
其他有用的保存方法:
●savaFieldId($name,$value)
○保存一个单field的值
●getLastInsertID()
○返回最近创建记录的ID
1.4 Model的Callbacks
在我们接近0.10.x最终版的时候,我们添加了一些model的回调函数,允许用户能够逻辑上悄悄的在model操作前或操作后执行。为了在应用中获得这种方法,在model中使用提供的参数,重载下面的这些方法
●beforeFind($conditions)
○这个回调函数在一个查询操作开始之前执行。将查询前的操作逻辑放到这个方法里面。当你在model中重写(override)这个方法时,当你想要find操作执行时候返回true,当你想要执行中止时候返回false
●afterFind($results)
○使用这个回调函数可以修改从find操作中返回的结果,或者实现其他任何的find后逻辑。这个函数的参数是model的find操作的结果,返回的是修改后的结果。
●beforeSave()
○在这个函数中放置任何保存前的逻辑。如果你像保存操作执行则返回true,否则返回false
●afterSave()
○放置任何你想要在保存后执行的代码在这个回调函数中
●beforeDelete()
○放置删除前的逻辑代码。想要删除操作执行则返回true,否则返回false
●afterDelete()
○放置任何你想要在删除后执行的代码在这个回调函数中
2. Model 变量
当你创建你的models时候,你可以设置一些特殊的变量,来获得对Cake函数的使用。
●$primaryKey
○如果这个model关联到一个数据库的table,而且数据库的主键并不是id,那么使用这个变量来告诉Cake主键的名字
●$transactional
○告诉Cake该model是否支持传输(举例 begin/commit/rolback),设置为boolea值。
●$useTable
○如果你想使用的数据库的table并不是model名的复数形式,而且你也不想改变table名,设置这个变量为table名
●$validate
○确认传递给model的数据是否正确的一个数组。查看第十章
●$useDbConfig
○还记得数据库设置中,你可以在/app/config/database.php文件中设置么?使用这个变量可以交换他们――仅仅使用数据库链接变量的名称你在database 配置文件中创建的。
3.联结(Associations)
链接是两个逻辑相关单元之间的关联。CakePHP中有四种类型的联结
●hasOne
●hasMany
●belongsTo
●hasAndBelongsToMany
因为他们比较容易混淆,所以最好举例来解释联结。
我们假设你有很多的书,有一天你坐在自己很大的图书馆里面,你突然觉得你应该将所有的书分下类。每一本书,你认为在分类里要有以下属性
●Title
●Author or Authors
●Short Description
●Categories
现在我们使用上面的例子来分别单独来看每种类型的关联
hasOne关联类型确定了这样一种情况:一个逻辑单元有一个且仅有一个其他的X类型的逻辑单元和它关联。在我们的分类例子中,每一本书都有且仅有一个title
hasMany关联类型确定了这样一种情况:一个逻辑单元有许多X类型的逻辑单元和它关联。在我们的分类例子中,每一本书可能有许多个不同的作者。
belongsTo关联类型是hasOne和hasMany关系的兄弟。一个逻辑断员属于另一个X类型的逻辑单元。一个作者属于一本书。注意到这个关系并不能确定这本书仅有一个还是有多个作者。从belongsTo关联你仅仅能得到的就是该作者属于这本书。查看这本书是否还所有其他作者,你必须使用这本书的关联关系,查看这本书是否有hasOne或hasMany关联到某些作者。
最后的关联hasAndBelongsToMany确定了这样一种情况:一个逻辑单元包含(has)许多其他的X类型的逻辑单元,这些X类型逻辑单元本身又有许多相互作用的单元。这个关联可能是最复杂的关联,但是我们也可以使用上面使用的分类例子来帮助我们更好的理解。
你可以根据下面的分类来归类每一本书
●科幻小说(Science Fiction)(Liuchen注:我们coder应该多看的书籍)
●传记
●幻想(Fantasy,不知道如何确切翻译)
●历史
现在假设你有一本Alan Turing(Liuchen注,还是不翻译成中文好,大家都知道是谁)的传记,这本书将属于(belong to)传记和历史两个分类,所以你可能认为这是hasMany关联,每一本书有许多的分类。但是,下一本书是空间编程(space program)的历史介绍,所以这本书也可以属于历史分类。这样就破坏了hasMany的规则,每一本书都可以有许多的分类,而且每个分类都可以属于多本书。这个就是hasAndBelongsToMany关联
CakePHP中这些关联需要做些什么呢?Cake可以控制许多在传统编程中各种错综复杂的关系,仅仅需要再controller中的一行代码。(原文:Cake can handle much of the blood, sweat, and tears that traditionally go into programming association with just a line of code in the controller.)我们创建一个table叫做books,每一本书都是table中的一个实体或记录,如下
Title
|
Author(s)
|
Description
|
Categories
|
|
|
|
|
开始,我们按照history of space exploration来归类,进展顺利。接着是Mr. Truing的历史自传这本书,我们遇到了麻烦。category只有一列,但是这本书却属于两个categories. 你也许认为这有两种解决方法
●将类别放到categories列,并使用逗号隔开,比如
history, biography
问题是如何选择,不久也许我们要通过categories列来找所有历史方面的书,但是你不能在SQL语句使用category=’history, biography’来代替 category=’history’ ,所以这不是一个好的解决办法
●为每个分类将一个实体放在table,如下面的形式:
第七章 Controllers
1.Controller 方法
1.1 和你的Views交互
1.2 使用Redirection
1.3 Controller的回调函数
1.4 其他有用的方法
2. Controller的变量
一个Controller是用来管理你应用某个方面的逻辑。大多数来说,controllers用来管理一个model的逻辑。比如,你正在建设一个站点来管理一个video的collection,你可能有一个VideoController以及一个RentalControlle来管理你的视频和租金。分别的,cake中每个controller的名字通常是复数。
程序的Controllers都是从AppController类继承来的类,AppController又是从核心的类Controller继承来的。Controller类可以包含任意数量的action:各种显示Views的方法
AppController类可以在/app/app_controller.php中第一,它里面包含了许多可以被更多controllers共享的方法,它本身是从核心类Controller继承来的。
一个Action是controller中的一个单独的方法,这个方法可以被Dispatcher自动的运行,运行的根据是从routes配置解析的页面请求。回到我们的 video collection的例子,VideoController类可以包含actions比如view(), rent(), search()等等,这个controller可以在/app/controllers/video_controller.php找到,并且文件内容为:
你可以通过使用下面的URLs来调用这些方法:
但是这些页面将如何显示?你需要为每个action定义一个view,你可以在下一章查看具体内容。但是本章中,你会掌握Cake的controller,并且能够更好的使用。具体的说,你将学到如何用controller将你的数据传递给view,使用户转向以及其他更多功能。
1. Controller Functions
重要:
尽管本章中介绍了许多Cake中常用的方法,更多的手册内容请参考http://api.cake.org
1.1 和views交互
●set($var,$value)
○这个方法是将controller中的数据传递给view的主要方法。你可以使用这个方法控制任何值:single values, 整个数组等等。一旦你使用了set(),view中也可以使用这个变量:在controller中使用set(‘color’,’blue’)可以使得$color变量在view中使用
●validate()
○通过收集错误的保存,返回错误的个数
●validateErrors()
○根据model中第一的正确性规则,检查一个model的数据是否正确,更多信息参考第十章
●render($action=null, $layout=null, $file=null)
○你并非时刻需要这个方法,因为在每个controller方法的最后,render都被自动调用,并且调用后定义(或者使用)相应的view
1.2 使用转向
●redirect($url)
○使用这个方法告诉用户将跳转到哪里。这里的URL可以使Cake规则的URL或者使一个完整定义的URL(http://...)
●flash($message, $url, $pause=1)
○这个方法在你的flash layout(app/views/layouts/flash.thtml)中显示$message信息$pause秒钟,之后跳转到指定的URL
1.3 Controller的回调函数
Cake Controller定义了一系列回调函数,你可以使用他们在重要的controller function之前或者之后插入功能逻辑。实现这些功能,适用下面介绍的参数和返回值声明这些方法
●beforeFilter()
○在每个controller action之前调用,非常有用的地方去检查sessions是否有效,并检查相应的权限
●afterFilter()
○在每个controlleraction之后调用
●beforeRender()
○在controller逻辑之后,view显示之前调用
1.4 其他有用的方法
尽管这些方法是在Cake的Object类中,他们在Controller中也可以使用
●requestAction($url, $extra=array())
○这个方法根据任何地方(location)调用controller的action,然后返回已经显示的view.$url是Cake规范的URL(/controllername/actionname/params),如果$extra数组包含了一个键‘render’,controller action将自动设置AutoRender
●log($msg, $type = LOG_ERROR)
○你可以使用这个方法在你的程序应中记录发生的任何事件。记录文件Logs放在/tmp文件目录下
2. Controller的变量
数量使用controller中定义的变量可以使你更好的使用cake的某些附加功能
●$name
○PHP4 并不能以驼峰表示法将当前类的名称提供给我们。如果你遇到问题,使用这个变量将你的类名设置成正确的驼峰表示法
●$uses
○你的controller是否使用了很多的model?比如你的Fragglescontroller会自动调用$this->fraggle,但是你也想同时能够调用$this->smurf,那就将下面的语句加入到你的controller中
●$helpers
○使用这个变量使得你的controller装在helpers到它的views. 这个HTML helper会自动装载,但是你可以使用这个变量来指定其他的
●$layout
○将这个变量设置成为你在这个controller中想使用的layout
●$autoRender
○将这个变量设置成为false将会使得actions停止自动显示(rendering)
●beforeFilter
○如果你需要在某一个或者任何一个action调用之前都要运行一小段代码,使用$beforefilter.这个函数处理access control十分有用,你可以在任何action处理之前检查用户的权限。你需要做的就是将这个变量设置成为一个数组,数组中包含了你想运行的controller的action,如下所示
第八章 Views
1.Views
一个View就是一个页面的模版,经常以action的名字来命名。举例来说,Postscontroller::add()方法的view存放在/app/views/posts/add.thtml。Cake的views文件都是简单的PHP文件,所以你可以在里面使用任何PHP代码,几乎所有的view文件都包含HTML,一个view可以使特定数据集的任何体现,包括XML,图片等等
在view的模版文件中,你可以从对应的Model中使用数据,这个数据以数组$data的形式传递过来,你在controller中使用set()传递过来的任何数据在view中都可以使用
注意
HTML helper默认情况下在任何一个view都是可用的。而且是views中使用最多的。它创建forms包括scripts和media、链接以及数据正确性检查中都非常有用。参考第九章第1.1节可以了解HTML helper更多的内容
views中许多可用的发放都是Helpers提供的。Cake提供了很多的helpers(参考第九章),你也可以引用自己定义的。因为views不应该包含过多的逻辑,所以views类中并没有很多public的方法。其中一个有用的方法就是renderElement(),这个方法我们在1.2节中讨论
1.1 Layouts
一个布局(layout)包括了围绕view的所有代码。你想在view中见到的所有东西都应该被放在你的layout中。 布局文件位于/app/views/layouts。
Cake的默认layout可以在/app/views/layouts/default.thtml被新的默认layout重写。一旦一个新的默认layout创建,controller view的代码将在页面被显示的时候替换到默认的layout
当你常见一个layout的时候,你需要告诉Cake你的controller view的代码位置:为了达到这个目的,一定要确保layout包含$content_for_layout(有$title_for_layout更好)下面是一
变量或者是setLayout()方法
举例来说,如果站点的一部分需要包含一个小的广告banner空间。可以创建一个新的带有小的广告空间的layout,并将这个layout设置成为controller actions将要使用的layout.方法如下:
1.2 Elements
很多应用都有一些很多页面都会重复的代码段,有时候在layout中的位置不相同。Cake可以帮助你重现这些需要复用的部分。这些复用的部分叫做元素(Elements)。广告,帮助框,导航控制条,额外的菜单,插图编号在cake中就被实现为元素。一个元素就是其他views可以引用的小型view(a mini-view)
元素位于 /app/views/elements文件夹,并且都有.thtml的文件扩展名
例 8.2 Calling an Element passing a data array
在一个元素文件中,所有传递的变量名称都是以通过传递过来数组的keys名获得(和controller中的set()在views中起到的作用很类似)。上面举的这个例子中 /app/views/elements/helpbox.thtml文件就会使用$helptext变量。当然,传递一个数组到元素文件会更有用的多。
使用元素可以使得view更易读,同时可以在一个文件中重复使用元素。他们也可以帮助你在网站建设中复用部分内容。
第九章 Helpers
Helpers设计的目的是提供一些方法,views通过使用这些方法能够更好的规范和显示数据。
1.1 HTML
HTML helper是Cake里快速开发,减少单调工作的一种途径。HTML helper有两个目的:为在HTML代码插入经常使用的代码提供帮助,为快速创建web form标单提供帮助。下面的这一节将会着重介绍这些方法,更多内容请参考http://api.cakephp.org
在HTML helper中许多方法都使用的HTML tag都是定义在 tags.ini.php。Cake的核心库中包含了一个tags.ini.php,但是如果你想做些改动,请在/app/conifg下面创建一份/cake/config/tags.ini.php. HTML helper将会使用这个文件中的tag定义来生成你需要的tags。使用HTML helper来创建自己的view代码将会非常有用,因为tags.ini.php文件中的改动将会在整个站点上都有显示。
另外,如果核心库文件(/app/config/core.php)中AUTO_OUTPUT被设置成true。hepler将会自动输出这些tag,而不是返回这些值。这样做是为了满足那些不喜欢在view中使用短标签(<?= ?>)或者许多echo()调用。包含$return参数的方法允许你该写自己的核心库配置。如果不考虑AUTO_OUTPUT的设置,你可以将$return设置为true这样html helper将会返回HTML代码。
HTML helper方法同样包含了$htmlAttibutes参数,这个参数是的你可以将其他的属性粘贴在标签上。比如,你想给一个标签添加一个class属性,你可以把下面这个作为$htmlAttribute的属性。
如果你想要在你的HTMl代码中插入正确组织的、经常使用的元素,HTML helper起到很大的作用。这里有四个方法可以插入media,协助tables,甚至用可视化的列表树创建基于PHP数组的未排序的列表。
●charset($charset,$return)
○这个方法可以创建一个charset的meta标签(META-tag)
●css($path ,$rel =’stylesheet’ , $htmlAttriutes= null , $return =false)
○创建一个css模版页(stylesheet),$rel参数允许用户提供一个 rel=value作为标签(原文:The $rel parameter allows you to provide a rel= value for the tag.)
●image($path, $htmlAttributes =null, $return=false)
○显示一个图片的标签。返回的代码可以用做link()方法的输入,这样就可以自动的产生一个linked images(liuchen注:我的理解就是创建了一个可以点击的图片,链接到别处)
●link($title,$url=null,$htmlAttributes=null,$confirmMessage=false,
$escapeTitle=True, $return=false)
○使用这个方法可以在view里面创建一个链接,$confirmMessage可以在你需要一条javascript的确认信息的时候使用,这样,点击这个链接则跳出这个确认信息,一条删除对象的链接经常需要一条“你确定么?”的确认信息,这样在删除之前要求用户的确认。如果你想让HTML helper不用管理你的数据(保存在$title变量中),可以将$escapeTitle设置成为true
●tableHeaders($names,$tr_options=null,$th_options=null)
○用来创建格式化的表格头
●tableCells($data,$odd_tr_options=null,$even_tr_options=null)
○用来创建格式化的表格单元
●guiListTree($data,$htmlAttributes=null,$bodyKey=’body’,
$childrenKey=’children’,$return=false)
○根据一个数组创建一个未排序的整齐的列表
一旦我们的controller建立,我们来看一下view的代码(位于app/views/notes/edit.thtml)。我们的Note model是非常简单的。而且仅仅包含了一个id,一个提交着的id和body。这个view 的代码意思是显示Note的数据并且让用户输入新的值并将提交的新值输到model中。
任何views默认情况下都可以得到HTML helper,使用$html就可以了。
特别的,可以看下面的table
错误信息将会有tagErrorMsg()方法显示在<div class=”error_message”></div>这个标签中,使用简单的CSS模式
下面是一些HTML helper可以创建的form tags(大多数都是直接创建)。
●formTag($target=null, $type=’post’,$htmlAttributes=null)
○创建一个打开的表单标签,使用$target来确定表单的action。记住,如果你要提交一个文件,你需要向$hatmAttrbutes参数提供合适的字符编码信息(?enctype infomation)
●submit($caption=’Submit’, $htmlAttributes=null, $return= false)
○通过$caption参数可以修改按钮名
●password($fieldName, $htmlAttributes=null, $return=false)
●textarea($fieldName, $htmlAttributes=null, $return = false)
●checkbox($fieldName, $title=null, $htmlAttributes=null, $return=false)
●file($fieldName, $htmlAttributes = null, $return=false)
●hidden($fieldName, $htmlAttributes=null, $return=false)
●input($fieldName, $htmlAttributes=null, $return=false)
●radio($fieldName,$options,$inbetween=null,$htmlAttributes=null,$return=false)
●tagErrorMsg($field, $text)
HTML helper 也包含了一系列方法来帮助创建数据库相关的 tag 。 $tagName 参数应该像 $filedName 参数一样处理。基金提供 date option tag 相关的 field name. 处理数据时,你可以在 controller 里面使用则各数据一直到该 field 的结尾。举例来说,如果我的 Note 有个 deadline 列(作为 data ),我的 dayOptionTag $tagName 参数被设置成‘ note/deadline ’,一旦表单被提交, day 数据将作为 $params 变量显示出来你可以使用这个来连接你的时间数据到跟你当前数据库配置相符合的形式。这段代码可以放在你尝试保存数据之前,保存到$data数组,这个数组可以用来保存信息到model中
例9.3 Concatenating time data before saving a mode(excerpt from NotesController)●dayOptionTag ($tagName, $value=null, $selected=null, $optionAttr=null)
●yearOptionTag ($tagName, $value=null, $minYear=null, $maxYear=null,
$selected=null, $optionAttr=null)
●monthOptionTag ($tagName, $value=null, $selected=null, $optionAttr=null)
●hourOptionTag ($tagName, $value=null, $format24Hours=false,
$selected=null, $optionAttr=null)
●minuteOptionTag ($tagName, $value=null, $selected=null, $optionAttr=null)
●meridianOptionTag ($tagName, $value=null, $selected=null, $optionAttr=null)
●dateTimeOptionTag ($tagName, $dateFormat= 'DMY', $timeFormat= '12',
$selected=null, $optionAttr=null)
1.2
Cake Ajax helper实现了更加popular的Prototype和script.aculo.us库赖提供Ajax操作和客户端效果。如果想使用这些helper,你必须有从http://script.aculo.us下载一份JavaScript libraries到/app/webroot/js目录下
这个helper里面的削夺方法多扩展了特殊的$options数组作为参数。这个数组用来确定你的Ajax操作中的各种东西
(liuchen:Ajax暂且略过,以后补充)
1.3 JavaScript
JavaScript helper用来帮助开发者输出标准的tag和数据
●codeBlock($script)
○用来返回$script,变量$script已经包含了<script>标签
●link($url)
○返回包含tag,指向特定$url指定script的脚本
●linkOut($url)
○跟link($url)的作用一样,就是参数$url不在本地
●escapeScript($script)
○Escapes carriage returns and single and double quotes for JavaScript code segments.
●event($object, $event, $observer, $useCapture=true)
○使用Prototype库,将一个事件链接到一个元素
●cacheEvents()
○缓存event()创建的JavaScript事件
●writeEvents()
○写cacheEvent()保存的内容
●includeScript($script=””)
○返回含有标签的JavaScript,一般是从Cake的js库中(/app/webroot/js/)
1.4 Number
Number helper包括一些在views中转化数字数据的方法
●precision ($number, $precision=3)
○返回由$precision确定的近似精度的值到$number中
●toReadableSize ($size)
○将bytes为单位的数字转化为用KB、MB、GB、TB等用户比较容易明白的数字
●toPercentage ($number, $precision=2)
○转化为百分数
1.5 Text
The Text Helper提供了一些方法,开发者可以使用这些方法来更好的将text输出到浏览器
●highlight ($text, $phrase, $highlighter= '< span class="highlight">\1</span >')
○将$text中所有$phrase都放在一个<span>标签里,返回$text
●stripLinks ($text)
○将所有的链接<a>标签都删除后返回
●autoLinkUrls ($text, $htmlOptions=array())
○将所有的URL自动添加<a>标签
●autoLinkEmails ($text, $htmlOptions=array())
○将所有的email地址自动添加<a>标签
●autoLink ($text, $htmlOptions=array())
○将所有的URL和email地址都自动添加<a>标签
●truncate ($text, $length, $ending='...')
○Returns the first $length number of characters of $text followed by $ending ('...' by default).(不明白)
●trim ()
○Alias for truncate().
●excerpt ($text, $phrase, $radius=100, $ending="...")
○Extracts an excerpt from the $text, grabbing the $phrase with a number of characters on each side determined by $radius.
●flay($text, $allowHtml=false)
○Text-to-html parser, similar to Textile or RedCloth, only with a little different syntax.
1.6 Time
Time Helper提供了一些方法,卡发者可以使用这些方法将时间方便的显示到浏览器上。时间可以提供的形式包括PHP的datatime字符串或者是Unix的时间戳
●fromString ($date_string)
○根据输入的两种类型的时间返回Unix时间戳
●nice ($date_string=null, $return=false)
○返回一个良好格式的时间字符串。比如Mon, Jan 1st 2005, 12:00
●niceShort ($date_string=null, $return=false)
○跟nice类似,就是返回昨天和今天的时候,返回Yesterday, 12:00和Today, 12:00
●isToday ($date_string)
○返回给定的时间是否是今天
●daysAsSql ($begin, $end, $field_name, $return=false)
○根据前后两个时间,返回一条sql查询语句,查找两个时间段内的记录
●dayAsSql ($date_string, $field_name, $return=false)
○返回给定时间内的所有记录
●isThisYear ($date_string, $return=false)
○返回是否是今年
●wasYesterday ($date_string, $return=false)
○返回是否是去年
●isTomorrow ($date_string, $return=false)
○返回是否是明天
●toUnix ($date_string, $return=false)
○返回Unix时间戳
●toAtom ($date_string, $return=false)
○Returns a date formatted for Atom RSS feeds.
●toRSS ($date_string, $return=false)
○格式化的RSS时间
●timeAgoInWords ($datetime_string, $return=false)
○Returns either a relative date or a formatted date depending on the difference between the current time and given datetime. $datetime should be in a strtotime-parsable format like MySQL datetime.
●relativeTime ($datetime_string, $return=false)
○Works much like timeAgoInWords(), but includes the ability to create output for timestamps in the future as well (i.e. "Yesterday, 10:33", "Today, 9:42", and also "Tomorrow, 4:34").
●wasWithinLast ($timeInterval, $date_string, $return=false)
○Returns true if specified datetime was within the interval specified, else false. The time interval should be specifed with the number as well as the units: '6 hours', '2 days', etc.
第十章 数据正确性(Data Validation)
创建用户的数据正确规则可以确保model中的数据能够按照程序的业务规则,比如密码必须是8个字符,用户名仅仅包含字母等等
保证数据正确性,第一步要做的就是在model中创建数据正确的规则。使用Model::validate这个数组在model中定义,比如
例10.1 /app/models/user.php
Validations定义使用perl的正则表达式,其中有一些事先定义在/libs/validators.php比如
如果model的定义中(比如在$validate数组)出现了任何的validateions,都会在保存过程中被转化和检查(比如在Model::save()方法中)。确保数据正确可以直接使用Model::validates()(如果数据不正确则直接返回false)或者Model::invalidFields()(这个方法返回错误信息的一个数组)
但是通常,controller代码中数据都是隐式的,下面的例子解释了如何创建一个处理form的方法
这个方法使用的view如下:
Controller::validates($model[,$model…])方法用来检查添加到model的用户数据是否正确。Controller::validationErrors()方法返回model得到的错误信息,这些信息被view的tagErrorMsg()方法显示出来
第十一章 访问控制表(Access Control Lists)
1 理解ACL如何工作
大多数权限很大的程序都需要某种形式的访问控制。ACL就是一种管理程序权限的简单持久的方法。ACL主要管理两件事情。需要东西的主体,和被需要的客体。在ACL系统中,想要东西的主体(经常情况下是用户)叫做access request objects,简称AROs。系统中被需要的客体(经常是方法或数据)叫做access control objects,简称ACOs。这些实体被成为objects是因为有时候被请求的object并不一定是人――有时候你可能想限制某个特定的Cake controller在程序其他的地方运行。ACOs可以是你想控制的任何东西,从一个controller的action,一个web服务,甚至是祖母的在线日记的一行。
一句话:ACL用来判断一个ARO是否可以访问一个ACO。
系统中有许多实体都会被请求(ACOs)。需要注意到,ACL并不是用来鉴别用户权限的系统。一颗能早有一种方法来存储用户的信息,当他们进入系统后也可以修改用户的身份。一旦你明白什么时用户,ACL就非常有用了。好,还是回到我们的话题
接下来,Gandalf需要做的就是做一份原始的表,列出ACO等系统可以管理的东西,可能如下所示:
你可能说这个矩阵已经可以很好的工作了,但是这个仅仅针对于一个较小的系统,当一个很大的逐渐增长的系统,这个矩阵可能就无法很好的处理,比如说有成千上万的武器……
ACL一般使用tree结构来事先。通常有个AROs的树和ACOs的树。举例如下:
通过这样构造树,我们可以将权限分配给其中的子节点。默认情况下,节点不可以访问任何东西。你可以顺着树往下,选择一些权限并实现他们。比如使用ACL可以如下:
如果你想用ACL来查看Pippin是否允许访问ale,我们首先在树中找到他的路径,在这个例子中是Fellowship-> Hobbites-> Pippin.接着我们可以看到许多不同的权限● Fellowship = DENY ale, so deny(因为设置的是不允许访问任何ACO)
● Hobbites = Allow Ale,所以允许
● Pippin ? 这个并没有说明特定的信息
● 最终结果,允许访问ale
(译注:大概的意思就是每个分类有个总的权限,可以是allow,也可以是deny,然后每个组员在整个组的权限基础上,还可以补充自己的权限。)
2确定权限:基于ini文件的Cake ACL
Cake最初ACL的实现是用iniw文件,尽管这种方法有用而且稳定,但是我们还是建议您使用基于数据库的ACL解决方案,这是因为创建新的ACO和ARO十分方便。这里,我们介绍ini主要是为了小型的开发,还有那些不想使用数据库的人。
ARO/ACO的权限定义在/app/config/acl.ini.php。对特定访问权限的介绍可以在文件的开头找到。类似于下面
使用ini文件,你可以确定一个用户,确定他所属的组,确定他自己的权限。你也可以确定组的属性。你可以在11.4节找到更多如何用ini进行用户权限的检查。
3. 定义权限:使用数据库
3.1 开始
默认的情况下,cake使用数据库来存储ACL访问权限。数据库ACL,或者dbACL有一组core models组组成,另外有命令行的脚本来执行Cake的安装。models用来插入或者查询ACL树。命令行脚本用来帮助你和树交互。
开始要做的是确保/app/config/database.php文件存在而且正确配置。接下来,使用ACL命令行脚本来初始化数据库并存数ACL信息。脚本位于/cake/scripts/acl.php,它为帮助你完成。在/cake/scripts/目录下用下面的命令来初始化命令
这时候,你就可以看到你数据库中添加了新的表。如果你对Cake如何存储树信息感到好奇,可以直接参看数据库中的信息。通常,acos和aros表存储节点信息,aros_acos表用来连接aros到可访问的acos
现在你就可以来创建你的AROs和ACOs树了。
3.2 创建AROS和ACOs
这里有两种方法来引用AROs/ACOs,第一种是给他们一个整数id,通常就是他们所属表的主键。另一种方法就是给他们一个字符串的别称。
创建一个新的ARO通常使用Aro Cake mode中定义的方法。Create()方法使用下面的参数:$link_id, $parent_id, $alias。这个方法创建了一个新的ACK对象,把$parent_id作为它的父亲(如果$parent_id是空,则该对象是根)。$link_id允许你把当前用户对象链接到一个ACL结构上。$alias参数允许使用一个非integer的id赋给对象。
举例说明:
你可以通过命令行脚本来创建ARO,脚本是 $acl.php create are <link_id> <parent_id> <alias>
创建ACO也是类似的
3.3 确定权限
一旦有用户创建,就可以将它的权限放到ACL树的对应位置,更多帮助可以使用命令行$php acl.php help
4 检查权限
通过在AppController使用ACL组件,你可以在程序的任何controller中使用它
第十二章 数据安全
1,使用Sanitize
Cake使用Sanitize来避免用户提交的恶意请求或者其他不希望的结果。Sanitize是一个核心库,所以你可以在代码的任何地方使用,但是最好还是在controllers或者models中使用
2.在SQL和HTML中使数据安全
本节主要介绍如何用Sanitize提供的方法
●paranoid($string, $allowed = array())
●sql($string)
添加/号使得SQL语句是小,/号取决于用户系统当前的magic_quotes_gpc设定
●cleanArray(&$toClean)
第十三章 cake的session组件
如果要使用数据库来存储session,可以在数据库中创建一个新的表,表的结构可以在/app/config/sql/sessions.sql找到
2. 使用cake的session组件
Cake seesion组件用来和session信息交互,包括基本的session的读写操作,同时也包括一些利用session表示信息的一些特性。如果你想使用session组件,确定有如下代码
下面是一些你可能使用的方法
●check($name)
○检查一下当前$name确定的key是否设置到session中
●del($name) and delete($name)
○删除$name确定的session
●error()
○返回最近的错误
●flash($key = 'flash')
○返回最新的使用setFlash()的信息,如果$key设置了,那么返回的是$key存储的信息●read($name = null)
○读$name确定的session
●renew()
○重新创建当前活跃的session,删除旧的id,并创建新的id,并将就的session值传递给新的session中
●setFlash($flashMessage, $layout = 'default', $params = array(), $key = 'flash')
○将$flashMessage中的message写入到session(或者待会儿被flash()取走),如果$layout设置成default,消息将会存储为'<div class="message">'.$flashMessage.'</div>'.如果设置为空, 消息将按照传递过来的样子存储。传递过来的信息将在Cake View中按照$layout存储起来。●valid()
○如果session可得,则返回true
●write($name, $value)
○将$name和$value确定的变量写入到当前活跃的session中
第十四章 处理请求组件(the request handler component)
1. 介绍
Request Handler组件用来监测HTTP请求的信息。你可以使用它在controller中更好的了解ajax请求,得到远程客户端的ip以及请求的类型,或者过滤掉不想要的信息,使用这个组件,你需要确定它在controller的$componets数组中,如下
2. 得到客户端或者请求信息
●getAjaxVersion()
○返回version
●getClientIP ()
○返回客户端ip
●getReferrer ()
○返回服务器名称
●isAjax()
○返回当前请求是否是XMLHttpRequest
●isGet()
○返回是否通过GET方法
●isMobile()
○返回是否移动浏览器
●isPost()
○返回是否是Post方法
●isPut()
○返回是否是Put方法
3. 过滤掉数据
有些情况下,你想要将请求或者输出中删除掉一些数据。
●stripAll($str)
○过滤掉空格,图像,脚本
●stripImages($str)
○过滤掉图像
●stripScripts($str)
○过滤掉脚本
●stripTags($str, $tag1, $tag2, $tag3...)
●stripWhitespace($str)
○过滤掉空格
4. 其他有用的方法
当用户请求中含有ajax请求,Request Handler组件就十分有用。setAjax()方法用来自动检测Ajax求情,并且设置controller的layout到请求的ajax layout。