CakePHP 手册

点击这里浏览 CakePHP 1.1.x 系列的手册

欢迎使用 CakePHP 的测试版 Cookbook 应用程序。我们希望通过这个测试版的 Cookbook 程序,能够达到以下几个目标:

  • 让用户更容易且有效地贡献文档
  • 让所发布的文档能够达到一定的水平

在此要特别感谢 AD7six。他是此 Cookbook 的发起人之一。正是因为他为此程序无私的付出,此程序才得以面世并得以应用。

# 那它是怎么运作的?

  1. 当您浏览这个手册,发现一些不完整、不全面,或一些不正确的词汇、语句
  2. 这时您可以使用您的 Bakery 帐号登陆此 Cookbook 应用程序
  3. 并且使用正确的 HTML 语法来修改、编辑或增添内容
  4. 几天后您就可以看到您所编辑的内容经过审核、并批准发放于 Cookbook 上

由于这是一个全新的应用程序,因此我们恳切地希望您能够谅解一切因最终版本发布时所作出的更正、调整而带来的不便。

# 翻译事项

如果您有兴趣加入我们翻译的行列,请发电邮至 "docs at cakephp dot org" 或在 IRC (#cakephp on freenode) 上直接与我讨论翻译的一些事宜。

翻译时须注意的事项:


本人全心全意地投入于制作这个文档,只希望它能够茁壮地成长。衷心地要求您一同加入编写手册的行列,使使用 CakePHP 的人们都能够从中获益。

敬上,

John David Anderson aka _psychic_
(docs at cakephp dot org)
CakePHP 文档

1 开始CakePHP之旅

美味的蛋糕...

1.1 什么是CakePHP? 为什么使用它?

CakePHP 是一个基于PHP免费开源的迅速发展框架。它提供程序员所需要的基本体系架构,因此程序员可以使用它更快速且不失灵活性地创建网络应用程序。而这就是我们创造 CakePHP 的首要目的。

大家对网络开发那千篇一律的步骤或许感到厌烦了。CakePHP 因此提供了开发一个网络程序时所需要的所有工具,您这时只需要编写程序里的详细逻辑就可以了。那每当您要开始一个新的程序的时候,您只需要把 CakePHP 给拷贝一份,接着就可以迅速地开始开发您的程序了。

CakePHP 拥有一个活跃的开发团队以及社区,使 CakePHP 本身更具备应有的价值。另外,使用 CakePHP 也意味着您的应用程序将更容易地测试以及更容易地被改良、更新。

使用 CakePHP 的好处:

  • 拥有既友好又活跃的社区
  • 灵活的MIT 许可证
  • 兼容 PHP4 和 PHP5
  • 数据库交互运用了 CRUD
  • 应用程序脚手架
  • 代码自动产生(代码产生器)
  • MVC 体系架构
  • 清晰,干净的高度自定义的URLs和路由请求分发器
  • 内建validation验证
  • 快速灵活的模板机制 (PHP syntax, with helpers)
  • 拥有AJAX, JavaScript, HTML表单和更多的视图助手工具
  • 邮件、Cookie、安全、会话(Session),和请求处理的组件
  • 灵活的ACL访问控制机制
  • 数据清理
  • 灵活的视图缓存Caching
  • 本地化
  • 可在任何子目录里工作,很少甚至不需要更改任何 Apache 相关配置

1.2 从哪里可以获得帮助

# CakePHP 官方网站 The Official CakePHP website

http://www.cakephp.org

CakePHP 官方网站永远是一个好地方。它链接到经常使用的开发工具, 演示录像 ,捐赠,和下载。

1.2.1 菜谱 The Cookbook

http://book.cakephp.org

这是你入门的好地方。这本手册,很可能是你首先应该去获取答案的地方。与很多其它开放源代码项目一样,我们常常会有新的朋友加入。尽量首先自己解决自己的问题。答案可能来得比较慢,但这样会减轻我们支持的负担。手册和API都有一个在线的部分。

# 糕点店 The Bakery

http://bakery.cakephp.org

CakePHP糕点店是为一切关于CakePHP的交流场所。看看指南,案例研究,和代码范例。一旦您熟悉了CakePHP ,登录社区并分享您的知识,获得即时的名气和财富。

# 应用编程接口 The API

http://api.cakephp.org/1.2

可以直接得到重点内容,这是由核心开发者做的文档, CakePHP的应用编程接口(API)是最全面的文件,它为框架的内部工作的所有细节做了最广泛的文档。它是一个直接代码参考,那么请带上你的竹蜻蜓吧。

# CakeForge

http://www.cakeforge.org

CakeForge是另一个开发资源,你可以与他人分享CakePHP项目。如果你正在寻找(或想分享)杀手级的组件,或值得称道的插件,请登录CakeForge 。

# The Test Cases

http://api.cakephp.org/tests

If you ever feel the information provided in the API is not sufficient, check out the code of the test cases provided with CakePHP 1.2. They can serve as practical examples for function and data member usage for a class. In your CakePHP distribution package the test cases are located under

cake/tests/cases
  1. cake/tests/cases
# IRC 聊天室 The IRC channel

#cakephp @ irc.freenode.net

如果你感到举步维艰,在cakePHP IRC频道给我们抱怨一下吧。开发团队的人经常在那里,特别是在夏令时间为北美洲和南美洲的用户。我们很乐意听到你的,你是否需要一些帮助,希望找出在你附近用户,或想捐出你的全新跑车。

# Google 网上论坛 The Google Group

http://groups.google.com/group/cake-php

CakePHP也有一个非常活跃的Google网上论坛。它是一个答案存档,你可以在其中进行查找,常见问题解答,并为你的眼前的问题获得答案。

1.3 理解MVC(Model-View-Controller)模式-视图-控制器

CakePHP遵循MVC软件开发模式。 程序开发设计使用MVC分开你的应用程序为三个主要的部分:

  1. 模型(Model):就是封装数据和所有基于对这些数据的操作。
  2. 视图(View):就是封装的是对数据显示,即用户界面。
  3. 控制器(Control):就是封装外界作用于模型的操作和对数据流向的控制等,简单来说就是负责处理和分发客户的请求。
Figure 1

图示 1:就是一个基本的MVC请求

图示 1显示了一个在CakePHP中的大概的MVC请求范例。举例说明,假设一个名叫"Ricardo"的客户刚刚点击了一个“现在购买一个客户自定义的Cake!”的链接在你的应用程序页面。

  • Ricardo 点击一个链接指向 http://www.example.com/cakes/buy, 并且他的浏览器向你的web server发送了一个请求。
  • 接着这个分发器检查 URL (/cakes/buy)请求,并且协助这个请求指到正确的控制器。
  • 这个控制器就会执行特定的应用程序逻辑。例如,他将检查看Ricardo是否已经登陆。
  • 这个控制器也使用模式去获得应用程序数据层的数据。模式通常展现数据库表,但是他们同时也展现(呈现) LDAP(轻量级目录访问协议)入口 entries, RSS feeds, 或者系统文件。在这个范例中, 这个控制器使用了一个模式(model)从数据库中去抓取、撷取Ricardo的最近的订单。
  • 一旦控制器已经开始魔法似的处理那些数据,他支配了那些数据成为一个视图。 视图的得到这个数据并且让它为展现给客户准备好。 在CakePHP视图通常是使用HTML格式, 但是一个视图应该能够很容易的成为一个 PDF, XML 文档, 或者 JSON 对象依赖于你的需求。
  • 一旦视图从控制器中获得数据就会呈现一个完成的编译好的视图给大家,那个视图的内容将会被返回到Ricardo的浏览器。

差不多每次请求你的应用程序都将遵循这个基本原则。稍后我们将会增加一些关于CakePHP这方面的细节,所以当我们继续下去时请谨记此点。

1.3.1 好处

为什么要用 MVC模式 呢? 因为它是一个经过考验的真正的软件设计模型,它可以使程序成为可维护的、模块化的和快速开发的包。使用分离的模型(Model)、视图(View)和控制器(Controller)组织的程序是轻便的。新的特性很容易就被加入,旧的程序换上新的外观也是一下子的功夫。模块化和分离的设计使得开发者和设计者能够同时工作,这包括了快速 原型的能力。分离的设计令开发者可以修改应用的一部分而不会影响到其他部分。

如果你从来没有用过这种方法建立应用,适应它需要一些努力,但是我们相信一旦你使用CakePHP建立了你的第一个应用,你不会再想用其他方法建立你的应用了。

2 CakePHP的基本原则

一个聪明的会话开始

2.1 CakePHP 結構

控制器,模型及视图是CakePHP的特色,除此之外它也包含了一些附加的类别及物件使得在MVC架构下开发较快速且更有乐趣。组件、行为及小帮手等类别提供可扩展性及可重用性来快速的新增功能到你的应用程序。就是现在,我们将站在较高的层级,接下来可以开始寻找如何使用这些工具的细节。

2.1.1 控制器扩展 Controller Extensions

组件是一个帮助简化控制器逻辑的类别。如果你有一些想要在控制器(或应用程序)之间共享使用的逻辑,那么组件通常是最适合的。像以下的一个简例,核心所提供的EmailComponent类别使得产生及传送email成为一个轻松的工作。而不是去另外重写传送email的方法在单一个控制器内,你可以包装这样的逻辑所以能被共享使用。

控制器也同样适用于回呼函式。这些回呼函式是可利用的,只需要在CakePHP的核心操作之中插入一些逻辑。 可利用的回呼函式包括:

  • beforeFilter(), 在所有的控制器动作逻辑开始之前执行
  • beforeRender(), 在控制器动作逻辑之后执行,但在视图输出之前
  • afterFilter(), 在所有的控制器动作逻辑之后执行,包括视图输出。 也许在afterRender()与afterFilter()之间没有什么不同,除非你手动在你的控制器动作之中呼叫render()以及包含一些逻辑在呼叫之后
2.1.2 视图扩展 View Extensions

小帮手是用来辅助视图逻辑的类别。与组件使用在控制器中非常类似,小帮手允许在多个视图中存取及共享显示逻辑。其中一个核心小帮手,AjaxHelper,使得Ajax请求在视图中应用更为简单

多数的应用程序多次的使用相同的视图片段。CakePHP使用布局(layouts)及元素(elements)使得重用视图代码更为容易。预设的情况下,每一个视图被控制器输出在布局内。元素被使用在当小片段代码的内容需要被重用在多个视图的时候。

2.1.3 模型扩展 Model Extensions

同样的,行为是用来加入常用功能在模型之中。举例来说,如果你储存使用者资料在树结构,你可以具体指定你的User模型使用像树结构的行为,并获得在你的树结构中自由操作移除、新增和搬移节点的功能

模型也支援另一个叫做DataSource的类别。DataSource是使得模型巧妙的运用不同的资料型态的抽像过程。当使用在CakePHP应用程序中的主要资料来源通常是资料库,你也许可以写附加的DataSource来允许你的模型表现RSS feeds、CSV files、LDAP entries 或 iCal events。DataSources允许你从不同的资料来源结合各种纪录,而不是只限制在使用SQL,DataSources也允许你透过你的LDAP模型关联到许多的iCal events。

就像控制器一样,模型也有良好使用回呼函式的特色

  • beforeFind()
  • afterFind()
  • beforeValidate()
  • beforeSave()
  • afterSave()
  • beforeDelete()
  • afterDelete()

这些方法的名字应该描述的够让你知道它的功用。你可以在模型的章节找到更详细的资讯

2.1.4 应用程式扩展 Application Extensions

控制器、小帮手、模型都有各自的父类别,你可以用来定义应用程式层次的更改。 AppController (控制器父类别档案位置 /app/app_controller.php), AppHelper (小帮手父类别档案位置 /app/app_helper.php) 以及 AppModel (模型父类别档案位置 /app/app_model.php)都是放置你想要在所有控制器、小帮手或模型共享功能的好地方。

尽管不是类别或档案,路由都在CakePHP扮演回应要求的角色。路由定义CakePHP如何对映URLs与控制器动作。预设的路由行为采用 "/controller/action/var1/var2" 对映至 Controller::action($var1, $var2),但是你可以使用路由来自订URLs以及它们如何在你的应用程式中解译

一些在应用程式中的特色是值得整个打包带走的。插件是一个实现了特定应用而包含了模型、控制器和视图的包裹,可以延申到多个应用程式之中。使用者管理系统或简单的部落格也许是一个相当适合的CakePHP插件

2.2 一次典型的CakePHP请求

我们已经看过CakePHP的基本成分了,那么现在就来看看各个对象怎么完成一个基本的请求。继续讲我们之前的请求的例子,想象一下我们的朋友Ricardo刚刚在一个CakePHP的应用的首页上点击了“立刻买一个自定义的蛋糕!”这个链接。

展示了一个典型的CakePHP请求的流程图

图2. 典型的Cake请求。

黑色 = 请求的元素, 灰色 = 可选的元素, 了;蓝色 = 回调方法

  1. Ricardo 点击了指向 http://www.example.com/cakes/buy 的链接, 然后他的浏览器对你的服务器发出了一个请求。
  2. 路由(route)从URL中解释并提取出这次请求的参数: 控制器(controller), 动作(action)以及其他在这次请求中影响到业务逻辑的所有其他参数。
  3. 使用路由后,请求的URL被映射到一个控制器的动作中(在特定的一个控制器的类的一个方法)。在这个例子,是CakeController类的buy()方法。在控制器的所有动作逻辑执行之前会调用beforeFilter()回调方法(callback)。
  4. 控制器可能会使用模型来处理应用的数据。在这个例子里,控制器使用了一个模型从数据里得到Ricardo上次买的东西。在这次操作中所有这个模型适用的回调方法、习惯(behavior)和数据源(DataSource)都可能得到实施。即使模型没有被用到,所有的CakePHP控制器的初始化至少都需要一个模型。
  5. 当模型取得数据后,数据会被返回到控制器。模型的回调方法可能会被实施。
  6. 控制器可能使用组件对数据进行进一步的加工,或者进行其他的操作(例如会话处理、验证或者发电子邮件)。
  7. 一旦控制器使用了模型和组件以有效地准备数据,就可以使用控制器的set()方法把数据传送到视图(view)。在数据送到视图前,控制器的回调方法可能会被实施。视图逻辑会被执行,可能包括了各种元素及(或者)帮助方法。默认情况下,视图会在一个布局(layout)里被渲染。
  8. 附加的控制器回调方法(像afterFilter)可能被实施。最后,完整的经过渲染的视图代码就被送到Ricardo的浏览器了。

2.3 CakePHP 档案结构

让我们来看看CakePHP的盒子里是用什么组成的。你知道CakePHP看起来像是从基本MVC组成的,但你也同样需要知道它档案是如何组织的。

  • app
  • cake
  • docs
  • index.php
  • vendors

当你下载了CakePHP,你将看到四个主要的资料夹。app资料夹将是你施展你的魔术之处:这是你放置你应用程式的地方。cake资料夹是我们施展我们魔法的地方,请不要修改这个资料夹里的所有档案,如果你修改而导致魔法失效,我们将无法帮助你除错。docs资料夹放置了典型的读我、版本更新记录及授权资料档案。最后,vendors资料夹是可以放置需要使用在你应用程式的第三方PHP函式库

2.3.1 App资料夹

CakePHP的app资料夹将是发展应用程式时最常使用的一个。就让我们来更仔细的看app资料夹里面有些什么

config 拥有一些CakePHP使用的设定。资料库连结的详细资料、启动组态、核心设定档案及许多应该被储存在这里的档案。
controllers 包含你的应用程式控制器及它们的组件。
locale 储存用来国际化的字元档案。
models 包含你的应用程式模型、行为和资料来源。
plugins 包含插件包裹。
tmp 这是用来储存CakePHP暂存资料的。实际上储存的资料是看你如何设定CakePHP,但这个资料夹通常用来储存模型描述、记录档和会谈资讯。
vendors 所有的第三方类别或函式库应该被放置在这个资料夹。可以简单的以App::import('vendor', 'name')使用它们。也许你会觉得多馀或困惑于此处有vendors而上一层目录内也有vendors资料夹,这其中的差异是当我们讨论到管理多应用程式和较为复杂的系统设定时,可以使用不同的配置。
views 展示层的档案被放置在此处:元素、错误页面、小帮手、布局和视图档案。
webroot 在产品安装模式下,这个资料夹应该是应用程式的根目录。包含了样式表、影像和JavaScript档案可放置的资料夹。

2.4 CakePHP命名規则

我们是命名规则的拥护者。虽然需要花费一点时间来学习CakePHP的命名规则,你省下更多时间在开发上:根据以下的命名规则,你得到不需花钱的功能,以及你将自己从搜寻设定档维护的恶梦中释放出来。命名规则达成一致的系统开发,允许其它的开发者较容易加入或是提供协助

CakePHP的命名规则从许多开发者多年的经验及一些惯例筛选出来。尽管我们建议你开发时使用命名规则,我们应该提及大部份这些规则简单又直观,特别是在修改旧有系统时较为轻松容易

2.4.1 档案及类别名称命名規则

一般来说,档案名称是由底线将文字分开,然而类别名称使用骆驼命名法。举例来说,类别KissesAndHugsController的档名会是kisses_and_hugs_controller.php。

档案名称不见得都像如此的约束,无论如何。类别EmailComponent的档名会是email.php,而类别HtmlHelper的档名会是html.php。

2.4.2 模型及资料库命名规则

模型类别名称是单数且使用骆驼命名法。Person、BigPerson、和ReallyBigPerson都是模型命名規则的例子。

资料表名称对应到CakePHP模型是复数且以底线分隔单字。资料表名称people、big_people和 really_big_people,会各自与上述的模型对应。

外键在hasMany、belongsTo或hasOne关系中随着相关模型在之后加上_id是被认可的。所以如果一个糕点师有许多饼乾,饼乾这个资料表透过baker_id外键将参考到糕点师这个资料表。

结合资料表,使用hasAndBelongsToMany (HABTM)关系在模型之间的命名方式必需依照字母先后次序(是apples_zebras而不是zebras_apples)

所有资料表与CakePHP模型互动(除了join资料表)需要有一个主键使每一列单一识别。如果你希望使用无单一识别主键的资料表,像是你的posts_tags结合资料表,CakePHP的命名规则就是加在资料表名称的单一主键。

CakePHP不支援复合主键。在这情况下你要直接操作你的结合资料表资料,这代表你需要使用直接查询呼叫或是增加主键来使用一般的模型。例如:

CREATE TABLE posts_tags (
id INT(10) NOT NULL AUTO_INCREMENT,
post_id INT(10) NOT NULL,
tag_id INT(10) NOT NULL,
PRIMARY KEY(id)); 
2.4.3 控制器命名規則

控制器的類別名稱是複數,使用駱駝命名法,並在最後加上ControllerPeopleControllerLatestArticlesController ,都是控制器命名規則的例子。

你寫一個控制器的第一個函數可能是index()函數。當一個請求是控制器而非動作的時候,預設的CakePHP行為是去執行控制器內的index()函數。例如一個http://www.example.com/apples/ 請求將映射至ApplesController叫用index()函數,而http://www.example.com/apples/view/ 會映射至ApplesController叫用view()函數。

您也可以由加上底線在控制器的函數名稱前來變更控制器能見度。如果一控制器的函數已加上底線,函式將不可直接從網站上取存,但是可以供內部使用。例如:

<?php
class NewsController extends AppController {

	function latest() {
		$this->_findNewArticles();
	}
	
	function _findNewArticles() {
		//Logic to find latest news articles
	}
}

?>
  1. <?php
  2. class NewsController extends AppController {
  3. function latest() {
  4. $this->_findNewArticles();
  5. }
  6. function _findNewArticles() {
  7. //Logic to find latest news articles
  8. }
  9. }
  10. ?>

頁面http://www.example.com/news/latest/ 可被一般使用者存取,有人想嘗試存取http://www.example.com/news/_findNewArticles/ 頁面將會得到錯誤訊息,因為這個函數已經被使用底線保護了。

2.4.3.1 关于控制器的地址的命名考虑

正如你所见,单个字母命名的控制器可以很容易的映射到一个简单的小写字母的地址上。. 例如, ApplesController (被定义成文件名为'apples_controller.php') 被http://example.com/apples访问。

多个单词命名的控制器can 的任何 'inflected(使词曲折变化)'如下的表示形式:

  • /redApples
  • /RedApples
  • /Red_apples
  • /red_apples

都能访问到RedApples controller的index()方法. 不管怎样, 按照命名规则的约定,你的url应该由小写字母和下划线组成, 因此/red_apples/go_pick 是正确命名格式去访问RedApplesController::go_pick action.

2.4.4 View Conventions

View template files are named after the controller functions they display, in an underscored form. The getReady() function of the PeopleController class will look for a view template in /app/views/people/get_ready.ctp.

The basic pattern is /app/views/controller/underscored_function_name.ctp.

By naming the pieces of your application using CakePHP conventions, you gain functionality without the hassle and maintenance tethers of configuration. Here’s a final example that ties the conventions

  • Database table: "people"
  • Model class: "Person", found at /app/models/person.php
  • Controller class: "PeopleController", found at /app/controllers/people_controller.php
  • View template, found at /app/views/people/index.ctp

Using these conventions, CakePHP knows that a request to http://example.com/people/ maps to a call on the index() function of the PeopleController, where the Person model is automatically available (and automatically tied to the ‘people’ table in the database), and renders to a file. None of these relationships have been configured by any means other than by creating classes and files that you’d need to create anyway.

Now that you've been introduced to CakePHP's fundamentals, you might try a run through the CakePHP Blog Tutorial to see how things fit together.

3 与CakePHP一起开发

现在你正在烹调

3.1 必要条件

  • HTTP Server. 最好是带 mod_rewrite模块的 Apacheis , 但不是必要条件.
  • PHP 4.3.2 或更高版本, 没错, CakePHP 可以在php4 或是5下面运行.

技术上来说, 数据库不是必需的,但我们设想每个应用都会用到数据库,cakephp 支持大部分数据库::

  • MySQL (4 or greater)
  • PostgreSQL
  • Firebird DB2
  • Microsoft SQL Server
  • Oracle
  • SQLite
  • ODBC
  • ADOdb

3.2 准备安装

3.2.1 Getting CakePHP

There are two main ways to get a fresh copy of CakePHP. You can either download an archive copy (zip/tar.gz/tar.bz2) from the main website, or check out the code from the SVN repository.

To download the latest major release of CakePHP. Visit the main website http://www.cakephp.org and follow the "Download Now" link.

All current releases of CakePHP are hosted at CakeForge, the home of CakePHP. This site also contains links to many other CakePHP projects, including plugins and applications for CakePHP. The CakePHP releases are available at http://cakeforge.org/projects/cakephp.

Alternatively nightly builds are produced which include bug-fixes and up to the minute(well, to the day) enhancements. These can be accessed from the download index here: http://cakephp.org/downloads/index/nightly. For true up to the minute updates, you can check out directly from the development branch of the svn repository here: https://svn.cakephp.org/repo/branches/1.2.x.x.

3.2.2 Permissions

CakePHP uses the /app/tmp directory for a number of different operations. Model descriptions, cached views, and session information are just a few examples.

As such, make sure the /app/tmp directory in your cake installation is writable by the web server user.

3.3 安装

安装CakePHP可以简单到直接把它丢入你网页伺服机的主目录中, 也可以复杂并如你希望般的弹性. 在这部分我们将含括三种安装方式: 开发模式, 实际应用与高级安装.

  • 开发模式: 简单又快速, URLs中将包含CakePHP的安装目录, 并不十分安全.
  • 实际应用: 必须调试伺服机之主目录, 简洁的URLs, 非常安全.
  • 高级安装: 通过一些调试, 能让你把CakePHP主程式放在指定的地方, 更可能让不同的CakePHP分享同样的CakePHP主程式.
3.3.1 开发

将CakePHP安装在你的网页伺服机的主目录中. 比如你的伺服机的主目录是/var/www/html, 在开发模式中目录排法如下:

  • /var/www/html
    • /cake_1_2
      • /app
      • /cake
      • /docs
      • /index.php
      • /vendors

在你的浏览器中输入http://www.example.com/cake_1_2/, 你将能够看到CakePHP.

3.3.2 实际应用

实际应用安装, 需要有在web伺服器中更改站点根目录的权限。这也表明整个域名将作为单一CakePHP应用运行。

实际应用安装使用如下步骤:

  • /path_to_cake_install/
    • /app
      • /webroot (此路径需要在WEB伺服器中设置为站点根路径)
    • /cake
    • /docs
    • /index.php
    • /vendors

若您使用的是Apache,则Apache配置文件中本站点的DocumentRoot指令可能和下面类似:

DocumentRoot /path_to_cake_install/app/webroot
  1. DocumentRoot /path_to_cake_install/app/webroot

要访问CakePHP, 以浏览器访问 http://www.example.com 即可.

3.3.3 Advanced Installation

There may be some situations where you wish to place CakePHP's directories on different places on the filesystem. This may be due to a shared host restriction, or maybe you just want a few of your apps to share the same Cake libraries. This section describes how to spread your CakePHP directories across a filesystem.

First, realize that there are three main parts to a Cake application:

  1. The core CakePHP libraries, in /cake.
  2. Your application code, in /app.
  3. The application’s webroot, usually in /app/webroot.

Each of these directories can be located anywhere on your file system, with the exception of the webroot, which needs to be accessible by your web server. You can even move the webroot folder out of the app folder as long as you tell Cake where you've put it.

To configure your Cake installation, you'll need to make some changes to /app/webroot/index.php. There are three constants that you'll need to edit: ROOT, APP_DIR, and CAKE_CORE_INCLUDE_PATH.

  • ROOT should be set to the path of the directory that contains your app folder.
  • APP_DIR should be set to the path of your app folder.
  • CAKE_CORE_INCLUDE_PATH should be set to the path of your CakePHP libraries folder.

Let’s run through an example so you can see what an advanced installation might look like in practice. Imagine that I wanted to set up CakePHP to work as follows:

  • The CakePHP core libraries will be placed in /usr/lib/cake.
  • My application’s webroot directory will be /var/www/mysite/.
  • My application’s app directory will be stored in /home/me/mysite.

Given this type of setup, I would need to edit my webroot/index.php file (which will end up at /var/www/mysite/index.php, in this example) to look like the following:

// /app/webroot/index.php (partial, comments removed) 

if (!defined('ROOT')) {
    define('ROOT', DS.'home'.DS.'me');
}

if (!defined('APP_DIR')) {
    define ('APP_DIR', 'mysite');
}

if (!defined('CAKE_CORE_INCLUDE_PATH')) {
    define('CAKE_CORE_INCLUDE_PATH', DS.'usr'.DS.'lib'.DS.'cake');
}
  1. // /app/webroot/index.php (partial, comments removed)
  2. if (!defined('ROOT')) {
  3. define('ROOT', DS.'home'.DS.'me');
  4. }
  5. if (!defined('APP_DIR')) {
  6. define ('APP_DIR', 'mysite');
  7. }
  8. if (!defined('CAKE_CORE_INCLUDE_PATH')) {
  9. define('CAKE_CORE_INCLUDE_PATH', DS.'usr'.DS.'lib'.DS.'cake');
  10. }

It is recommended to use the DS constant rather than slashes to delimit file paths. This prevents any missing file errors you might get as a result of using the wrong delimiter, and it makes your code more portable.

3.3.3.1 Additional Class Paths

It’s occasionally useful to be able to share MVC classes between applications on the same system. If you want the same controller in both applications, you can use CakePHP’s bootstrap.php to bring these additional classes into view.

In bootstrap.php, define some specially-named variables to make CakePHP aware of other places to look for MVC classes:

$viewPaths        = array();
$controllerPaths  = array();
$modelPaths       = array();
$helperPaths      = array();
$componentPaths   = array();
$behaviorPaths    = array();
  1. $viewPaths = array();
  2. $controllerPaths = array();
  3. $modelPaths = array();
  4. $helperPaths = array();
  5. $componentPaths = array();
  6. $behaviorPaths = array();

Each of these special variables can be set to an array of absolute filesystem paths where extra classes can be found when requested. Make sure that each path specified includes a trailing slash.

3.3.4 Apache and mod_rewrite

While CakePHP is built to work with mod_rewrite out of the box–and usually does–we've noticed that a few users struggle with getting everything to play nicely on their systems. Here are a few things you might try to get it running correctly:

  • Make sure that an .htaccess override is allowed. In your httpd.conf, you should have a section that defines your Directory on the server. Make sure the AllowOverride is set to All for the correct DocumentRoot.
  • Make sure you are editing the system httpd.conf rather than a user- or site-specific httpd.conf.
  • Is CakePHP missing its needed .htaccess files? This sometimes happens during copying or moving because some operating systems treat files that start with '.' as hidden. Make sure your copy of CakePHP is from the downloads section of the site or our SVN repository, and has been unpacked correctly.
  • Make sure you are loading up mod_rewrite correctly. You should see something like LoadModule rewrite_module libexec/httpd/mod_rewrite.so (Unix/Linux users should also see something like AddModule mod_rewrite.c) in your httpd.conf. Also make sure that those lines have not been commented out (by being prepended with a #). Restart Apache to make sure your conf settings are active.
  • If you are installing CakePHP into a user directory (http://example.com/~username/cakephp/), or any other URL structure that already utilizes mod_rewrite, you'll need to add RewriteBase statements to the .htaccess files CakePHP uses (/.htaccess, /app/.htaccess, /app/webroot/.htaccess). The details of those changes will depend on your setup. Please refer to Apache's online documentation for more information.
3.3.5 Fire It Up

Alright, let's see CakePHP in action. Depending on which setup you used, you should point your browser to http://example.com/ or http://example.com/cake_install/. At this point, you'll be presented with CakePHP's default home, and a message that tells you the status of your current database connection.

Congratulations! You are ready to create your first CakePHP application.

3.4 配置

3.4.1 数据库配置

CakePHP 会将数据库配置放到app/config/database.php 中。app/config/目录下默认的只有database.php.default文件,可以复制一份并命名为database.php,配置后的内容如下:

var $default = array('driver'      => 'mysql',
                     'persistent'  => false,
                     'host'        => 'localhost',
                     'login'       => 'cakephpuser',
                     'password'    => 'c4k3roxx!',
                     'database'    => 'my_cakephp_project',
                     'prefix'      => '');
  1. var $default = array('driver' => 'mysql',
  2. 'persistent' => false,
  3. 'host' => 'localhost',
  4. 'login' => 'cakephpuser',
  5. 'password' => 'c4k3roxx!',
  6. 'database' => 'my_cakephp_project',
  7. 'prefix' => '');

数据库连接配置默认都会使用$default,除非在model有新的连接,并用$useDbConfig等于新的连接进行赋值。举例:在我的实例中除了默认的数据库,还有另一个legacy数据库,我可以创建一个新的legacy数据库的连接数组(跟$default类似),在model里通过var $useDbConfig = 'legacy';进行数据库切换。

根据你的需求填写配置数组中key/value对的值。

Key Value
driver 数据库驱动的名字,CakePHP支持的数据库驱动有mysql, postgres, sqlite, pear-drivername, adodb-drivername, mssql, oracle, odbc.
persistent 是否使用数据库永久连接
host 数据库服务器的主机名或者IP地址
login 数据库登陆帐户的用户名
password 数据库登陆帐户的密码
database 你将使用的数据库名
prefix (可选) 数据库中表的前缀,如果你的表没有前缀直接将这个参数设为空字符串
port (optional) 连接数据库的TCP端口或者Unix socket
encoding 指定发送数据库查询语句到服务器的编码格式
schema 用于 PostgreSQL 数据库中,指定哪个计划将被使用

请注意这里的前缀只针对数据库中的表,并不针对model, 举例:如果你将前缀设置为 'prefix_',而你将要创建一个关联Apple,Flavor两个model的关联表,这个表的表名将是prefix_apples_flavors(而不是 prefix_apples_prefix_flavors)

关于这点,你可以参考CakePHP Conventions的附录,用CakePHP命名规则来给数据库表取名可以省掉你很多的配置,并且能获得很多功能。如果表名为:big_boxes,那么model就应该是BigBox,controller:BigBoxesController。为了使用方便,表的名字应该用小写的英文单词的复数形式,单词与单词之间用下划线分隔,bakers, pastry_stores, savory_cakes都是正确的表名。

3.4.2 全局配置

CakePHP的全局配置文件为/app/config/core.php 配置类的变量定义以及常量定义都在这个文件里,并决定了你所做的实例的运行方式。在设置这些变量前,你最好熟悉配置,以及CakePHP的配置注册类

3.4.3 The Configuration Class

尽管CakePHP不需要配置很多东西,但有时候你设置一些自己的配置会对你的实例起到很大的帮助。过去我们可能会在文件中定义一些变量或者常量进行赋值。但是每次你要用到这些变量或者常量的时候,你必须要将这个文件用include()函数包含进来。

CakePHP的最新的配置类可以存储特定的值,并能重新得到这些值。但是请注意,这个类允许保存任何东西,并且可以在程序的任何部分进行调用,因此很有可能会改掉CakePHP设定的MVC的参数。这个类的主要目的是为了让几个主要的变量可以在不同的对象中都能进行调用。请记住你所设定的值不要破坏MVC的结构

这个类是独立类,可以在任何地方用这个类的实例调用它的函数,

<?php Configure::read('debug'); ?>
  1. <?php Configure::read('debug'); ?>
3.4.3.1 Configure Methods
3.4.3.1.1 write()函数
write(string $key, mixed $value)
  1. write(string $key, mixed $value)

用write()函数保存实例的配置数据。

Configure::write('Company.name','Pizza, Inc.');
Configure::write('Company.slogan','Pizza for your body and soul');
  1. Configure::write('Company.name','Pizza, Inc.');
  2. Configure::write('Company.slogan','Pizza for your body and soul');

请注意$key参数中的圆点符号(.), 你可以使用这个符号来整理你的配置逻辑集合。

可以把上面的两个例子合并和一个:

Configure::write(
    'Company',array('name'=>'Pizza, Inc.','slogan'=>'Pizza for your body and soul')
);
  1. Configure::write(
  2. 'Company',array('name'=>'Pizza, Inc.','slogan'=>'Pizza for your body and soul')
  3. );

你也可以用 Configure::write(‘debug’, $int) 及时切换debug和production的状态。AMF或者SOAP在交互时特别好用这个函数,因为调试信息可能会导致解析的问题

3.4.3.1.2 read()函数
read(string $key = 'debug')
  1. read(string $key = 'debug')

用来读取实例中的配置参数,默认值是'debug',通过键名来返回对应的值。下面是在上一部分的write()函数例子的基础上得到的数据。

Configure::read('Company.name');    //返回结果: 'Pizza, Inc.'
Configure::read('Company.slogan');  //返回结果: 'Pizza for your body and soul'
 
Configure::read('Company');
 
//返回结果: 
array('name' => 'Pizza, Inc.', 'slogan' => 'Pizza for your body and soul');
  1. Configure::read('Company.name'); //返回结果: 'Pizza, Inc.'
  2. Configure::read('Company.slogan'); //返回结果: 'Pizza for your body and soul'
  3. Configure::read('Company');
  4. //返回结果:
  5. array('name' => 'Pizza, Inc.', 'slogan' => 'Pizza for your body and soul');
3.4.3.1.3 delete()函数
delete(string $key)
  1. delete(string $key)

用来删除实例的配置信息

Configure::delete('Company.name');
  1. Configure::delete('Company.name');
3.4.3.1.4 load()函数
load(string $path)
  1. load(string $path)

从特殊文件中加载配置信息

// /app/config/messages.php:
<?php
$config['Company']['name'] = 'Pizza, Inc.';
$config['Company']['slogan'] = 'Pizza for your body and soul';
$config['Company']['phone'] = '555-55-55';
?>
 
<?php
Configure::load('messages');
Configure::read('Company.name');
?>
  1. // /app/config/messages.php:
  2. <?php
  3. $config['Company']['name'] = 'Pizza, Inc.';
  4. $config['Company']['slogan'] = 'Pizza for your body and soul';
  5. $config['Company']['phone'] = '555-55-55';
  6. ?>
  7. <?php
  8. Configure::load('messages');
  9. Configure::read('Company.name');
  10. ?>

请注意在这个例子中当你调用load()函数之后,$config数组只替换与他有相同键名的变量的值,其他变量将被忽略。

3.4.3.1.5 version()函数
version()
  1. version()

返回当前使用的CakePHP版本号.

3.4.3.2 CakePHP 内核配置变量

配置类通常用于设置CakePHP的核心配置变量,这些变量在app/config/core.php文件中。下面是这些变量的描述以及他们对CakePHP产生的影响。

变量名 描述
debug 设置CakePHP的调试的输出模式

0 = 没有输出结果
1 = 显示错误信息和警告
2 = 显示错误信息,警告和数据库查询语句
3 = 显示错误信息,警告和数据库查询语句,完成控制器转储
App.baseUrl 不要注释掉这个定义如果你不打算使用Apache的mod_rewrite. 同时不要忘记删除.htaccess文件
Routing.admin 不要注释掉这个变量如果你要用CakePHP的路由(admin route),变量值跟路由的名字相同,接下来会介绍更多。
Cache.disable 设成true的时候,整个网站的缓存会被关闭。
Cache.check 如果设成true, 开启视图缓存。虽然控制器缓存需要另外开启,但是这个变量可以监控这些设置。
Session.save CakePHP的session存储机制

php = 使用默认的PHP session存储
cake = 将session数据保存到/app/tmp目录下
database = 将session保存到数据库表中。但要保证使用/app/config/sql/sessions.sql 这个数据库查询文件来设置表。
Session.table 存储session的表名,不包括前缀
Session.database 存储session的数据库名字
Session.cookie 追踪session的cookie的名字
Session.timeout session超时的时间,以秒为单位,实际值以Security.level为基准
Session.start 如果为true,sessions自动开启
Session.checkAgent 如果为false,session不会检查各个请求之间的用户没有改变
Security.level CakePHP安全等级。安全等级的值决定了Session.timeout的值

Valid values:
'high' = x 10; 最高安全级别,10分钟没有活动的session被置为超时,同时每一次请求都将生成新的session id
'medium' = x 100; 100分钟没有活动的session被置为超时
'low' = x 300; 300分钟没有活动的session被置为超时
Security.salt 一个随机的字符串用在安全散列法中
Acl.classname, Acl.database 常量,用在CakePHP访问控制列表功能化中。更多内容请参考访问控制列表章节

请注意:core.php文件中也有缓存配置,我们会在后面讲解

配置类可以即时地修改内核配置,这个相当方便,特别是在调试一小段逻辑的时候

3.4.3.3 Configuration Constants

尽管大部分配置选项的值都是设定的, CakePHP在运行时还是会使用一些常量

常量 描述
LOG_ERROR 错误常量,用于鉴别错误日志记录和调试。目前, PHP支持LOG_DEBUG
3.4.4 App类

CakePHP可以加载其他类。在前一个版本中加载不同类型的类需要条用不同的函数。现在加载函数以及库只要用一个函数就可以完成 App::import()。App::import()保证每个类只加载一次,合适的父类被加载后,路径问题就会自动解决

App::import() 函数的使用

<?php App::import($type, $name, $parent, $search, $file, $return); ?>
  1. <?php App::import($type, $name, $parent, $search, $file, $return); ?>

第一眼看到App::import觉得他很复杂, 其实在调用时只有两个参数是必须要填的,其他的都可以不填

加载内核函数库

下面是加载内核的函数库(包括Sanitize ,Xml)的例子:

<?php App::import('Core', 'Sanitize') ?>
  1. <?php App::import('Core', 'Sanitize') ?>

上面的例子必须保证Sanitize类可以使用.

加载控制器(Controllers), 模块(Models), 组件(Components), 行为(Behaviors)以及帮助(Helpers)

所有的应用都要用App::import()来加载,接下来我们将举例说明:

加载控制器(Controllers)

App::import('Controller', 'MyController');
  1. App::import('Controller', 'MyController');

加载模块(Models)

App::import('Model', 'MyModel');
  1. App::import('Model', 'MyModel');

加载组件(Components)

App::import('Component', 'Auth');
  1. App::import('Component', 'Auth');

加载行为(Behaviors)

App::import('Behavior', 'Tree');
  1. App::import('Behavior', 'Tree');

加载帮助(Helpers)

App::import('Helper', 'Html');
  1. App::import('Helper', 'Html');

从插件中加载

在插件中加载类与加载app,core类几乎一样,除了你必须指定是从哪个插件里加载的。

App::import('Model', 'PluginName.Comment');
  1. App::import('Model', 'PluginName.Comment');

加载Vendor文件

vendor()函数已经不再使用了. Vendor文件也要用App::import()方法来加载. 语法以及额外的参数有点小小的变化,因为vendor文件的结构已经有很大的变化,而且并不是所有的vendor文件都包含类

下面的例子解释了怎么样从不同的目录里加载vendor文件,这些文件可以当在vendor目录的任何位置

Vendor例子

加载vendor/geshi.php

App::import('Vendor', 'geshi');
  1. App::import('Vendor', 'geshi');

加载vendor/flickr/flickr.php

App::import('Vendor', 'flickr/flickr');
  1. App::import('Vendor', 'flickr/flickr');

加载vendor/some.name.php

App::import('Vendor', 'SomeName', array('file' => 'some.name.php'));
  1. App::import('Vendor', 'SomeName', array('file' => 'some.name.php'));

加载vendor/services/well.named.php

App::import('Vendor', 'WellNamed', array('file' => 'services'.DS.'well.named.php'));
  1. App::import('Vendor', 'WellNamed', array('file' => 'services'.DS.'well.named.php'));
3.4.4.1 Using App::import()

App::import($type, $name, $parent, $search, $file, $return);

At first glance App::import seems complex, however in most use cases only 2 arguments are required.

3.4.4.2 Importing Core Libs

Core libraries such as Sanitize, and Xml can be loaded by:

App::import('Core', 'Sanitize');
  1. App::import('Core', 'Sanitize');

The above would make the Sanitize class available for use.

3.4.4.3 Importing Controllers, Models, Components, Behaviors, and Helpers

All application related class should also be loaded with App::import(). The following examples illustrate how to do so.

3.4.4.3.1 Loading Controllers

App::import('Controller', 'MyController');

3.4.4.3.2 Loading Models

App::import('Model', 'MyModel');

3.4.4.3.3 Loading Components

App::import('Component', 'Auth');

3.4.4.3.4 Loading Behaviors

App::import('Behavior', 'Tree');

3.4.4.3.5 Loading Helpers

App::import('Helper', 'Html');

3.4.4.4 Loading from Plugins

Loading classes in plugins works much the same as loading app and core classes except you must specify the plugin you are loading from.

App::import('Model', 'PluginName.Comment');
  1. App::import('Model', 'PluginName.Comment');
3.4.4.5 Loading Vendor Files

The vendor() function has been deprecated. Vendor files should now be loaded through App::import() as well. The syntax and additional arguments are slightly different, as vendor file structures can differ greatly, and not all vendor files contain classes.

The following examples illustrate how to load vendor files from a number of path structures. These vendor files could be located in any of the vendor folders.

3.4.4.5.1 Vendor examples

To load vendors/geshi.php

App::import('Vendor', 'geshi');
  1. App::import('Vendor', 'geshi');

To load vendors/flickr/flickr.php

App::import('Vendor', 'flickr/flickr');
  1. App::import('Vendor', 'flickr/flickr');

To load vendors/some.name.php

App::import('Vendor', 'SomeName', array('file' => 'some.name.php'));
  1. App::import('Vendor', 'SomeName', array('file' => 'some.name.php'));

To load vendors/services/well.named.php

App::import('Vendor', 'WellNamed', array('file' => 'services'.DS.'well.named.php'));
  1. App::import('Vendor', 'WellNamed', array('file' => 'services'.DS.'well.named.php'));
3.4.5 路由配置

路由用来映射URL和控制器的action。有了它,你可以灵活地设置自己想要的URL。使用Apache的mod_rewrite并不一定要用路由,只是路由可以使你的地址栏变得更加精简

CakePHP 1.2对路由进行了扩展,并使它变得非常强大

默认路由

学习配置路由之前,你得知道CakePHP自身就会设定一组路由的值。CakePHP的默认值在任何实例中都能完美地应用。你可以在地址栏里直接打入请求需要的名字来访问控制器的action.你也可以地址栏来传递变量给控制器的action.

    URL样式的默认格式:
    http://example.com/controller/action/param1/param2/param3
  1. URL样式的默认格式:
  2. http://example.com/controller/action/param1/param2/param3

URL中/posts/view会映射到Post控制器PostsController的view()函数上,/products/viewClearance对应ProductsController的view_clearance()函数, 如果URL中没有设定action,就直接调用index()函数

默认的路由配置允许通过地址来传递参数。/posts/view/25 这个请求相当于调用PostsController的view(25)函数

命名的参数

CakePHP 1.2允许使用命名的参数,通过URL你可以自定义一些参数名并传递他们的值。/posts/view/title:first+post/category:general 这样的请求会调用PostsController的view()函数,你会发现title和category这两个变量分别在$this->passedArgs[‘title’]和$this->passedArgs[‘category’]在里面

一些使用默认路由的例子或许已经证明它的好处

使用默认的路由配置实现URL到控制器action的映射
    
URL: /monkeys/jump
映射: MonkeysController->jump();
 
URL: /products
映射: ProductsController->index();
 
URL: /tasks/view/45
映射: TasksController->view(45);
 
URL: /donations/view/recent/2001
映射: DonationsController->view('recent', '2001');

URL: /contents/view/chapter:models/section:associations
映射: ContentsController->view();
$this->passedArgs['chapter'] = 'models';
$this->passedArgs['section'] = 'associations';
  1. 使用默认的路由配置实现URL到控制器action的映射
  2. URL: /monkeys/jump
  3. 映射: MonkeysController->jump();
  4. URL: /products
  5. 映射: ProductsController->index();
  6. URL: /tasks/view/45
  7. 映射: TasksController->view(45);
  8. URL: /donations/view/recent/2001
  9. 映射: DonationsController->view('recent', '2001');
  10. URL: /contents/view/chapter:models/section:associations
  11. 映射: ContentsController->view();
  12. $this->passedArgs['chapter'] = 'models';
  13. $this->passedArgs['section'] = 'associations';

定义路由

自定义路由就相当于定义了你的实例如何响应URL。在/app/config/routes.php文件里通过Router::connect()函数定义你的路由

connect()函数有三个参数:你希望匹配的URL值,自定义的路由元素的默认值,帮助该路由器匹配的URL元素的正则表达式的规则

路由定义的最基本的格式:

Router::connect(
    'URL',
    array('paramName' => 'defaultValue'),
    array('paramName' => 'matchingRegex')
)
  1. Router::connect(
  2. 'URL',
  3. array('paramName' => 'defaultValue'),
  4. array('paramName' => 'matchingRegex')
  5. )

第一个参数定义URL类型。URL通常由斜杠分割的,但是也会包含一些通配符(*)或者自定义路由元素(URL元素以冒号为前缀), 用通配符来匹配URL的类型。特殊化的路由元素允许你为你的控制器actions收集参数。

一旦你特殊化了一个URL,你要用connect()函数的最后两个参数告诉CakePHP匹配成功后该如果处理请求。第二个参数是个关联数组。如果URL里面有路由元素数组的键就要命名,或者使用默认的元素 :controller, :action, :plugin。数组的值就使用默认值。在介绍第三个参数之前让我们先来看几个例子。

Router::connect(
    '/pages/*',
    array('controller' => 'pages', 'action' => 'display')
);
  1. Router::connect(
  2. '/pages/*',
  3. array('controller' => 'pages', 'action' => 'display')
  4. );

你可以在routes.php文件里找到这个配置。这个路由可以匹配任何以/pages/开头的网址,然后指定到page控制器PagesController()的display()函数,举例:/pages/products对应PagesController->display(‘products’);

Router::connect(
    '/government',
    array('controller' => 'products', 'action' => 'display', 5)
);
  1. Router::connect(
  2. '/government',
  3. array('controller' => 'products',