REST
尽管还有其它解决方法,REST 是一个很棒的方法,为你在应用程序中创建的逻辑提供容易的访问方式。这是简单的、通常基于 XML 的(我们谈论是简单的 XML,完全不象 SOAP 信封(envelope)那么复杂),依赖于 HTTP 标头(headers)信息来提供指令。在 CakePHP 中通过 REST 提供 API 很简单。
开始使用 REST 最快捷的方法,只需在 app/Config 目录中的 routes.php 文件中添加几行。Router 对象带有一个 方法,用来为控制器的 REST 访问设置一些默认的路由。确保 mapResources()
方法出现在require CAKE . 'Config' . DS . 'routes.php';
和其它会改变路由的路由。如果要允许以 REST 方式访问菜单(recipe)数据库,就要象下面这样:
第一行为简单的 REST 访问建立一些默认路由,而 parseExtensions()
方法指定想要的结果格式(例如 xml、json、rss)。这些路由能够辨识 HTTP 请求的方法(Method)。
CakePHP 的 Router 类使用一些不同的指标来检测使用的 HTTP 方法。下面按优先顺序排列:
- The _method POST variable
- The X_HTTP_METHOD_OVERRIDE
- The REQUESTMETHOD header
__method POST 变量有助于使用浏览器(或者任何其它可以容易地 POST 的工具)作为REST 客户端。只需设置 _method 为要模拟的 HTTP 请求方法的名称。
一旦路由器设置好,映射 REST 请求到某些控制器动作(controller action),我们就可以继续创建控制器动作内的逻辑。基本的控制器可以象这样:
- // Controller/RecipesController.php
- class RecipesController extends AppController {
- public $components = array('RequestHandler');
- public function index() {
- $recipes = $this->Recipe->find('all');
- $this->set(array(
- 'recipes' => $recipes,
- '_serialize' => array('recipes')
- ));
- }
- public function view($id) {
- $recipe = $this->Recipe->findById($id);
- $this->set(array(
- 'recipe' => $recipe,
- '_serialize' => array('recipe')
- ));
- public function add() {
- $this->Recipe->create();
- if ($this->Recipe->save($this->request->data)) {
- $message = 'Saved';
- } else {
- $message = 'Error';
- }
- $this->set(array(
- 'message' => $message,
- '_serialize' => array('message')
- ));
- }
- public function edit($id) {
- $this->Recipe->id = $id;
- if ($this->Recipe->save($this->request->data)) {
- $message = 'Saved';
- } else {
- $message = 'Error';
- }
- $this->set(array(
- 'message' => $message,
- '_serialize' => array('message')
- ));
- }
- public function delete($id) {
- if ($this->Recipe->delete($id)) {
- $message = 'Deleted';
- } else {
- $message = 'Error';
- }
- $this->set(array(
- 'message' => $message,
- '_serialize' => array('message')
- ));
- }
- }
如果要在数据转换为 XML 之前对其进行改动,就不要定义 _serialize
视图变量,而是使用视图文件。把 RecipesController 控制器的 REST 视图放在 目录中。也可以使用 Xml
类,在这些视图中进行快捷的 XML 输出。index 视图可以象下面这样:
当使用 parseExtensions() 方法提供一个特定的内容类型时,CakePHP 会自动寻找匹配类型的视图助件。因为使用 XML 为内容类型,没有内置的助件,不过如果你要创建一个,就会在这些视图中自动加载以供使用。
最终渲染的 XML 会象这样:
- <recipes>
- <recipe id="234" created="2008-06-13" modified="2008-06-14">
- <author id="23423" first_name="Billy" last_name="Bob"></author>
- <comment id="245" body="Yummy yummmy"></comment>
- </recipe>
- <recipe id="3247" created="2008-06-15" modified="2008-06-15">
- <author id="625" first_name="Nate" last_name="Johnson"></author>
- <comment id="654" body="This is a comment for this tasty dish."></comment>
- </recipe>
- </recipes>
创建 edit 动作的逻辑有一点复杂,但也不算太复杂。既然是提供输出 XML 的 API,选择接受 XML 就很自然。不用担心,RequestHandler
和 类使事情容易得多。如果 POST 或 PUT 请求有 XML 内容类型(content-type),那么输入就会经过 CakePHP 的 Xml
类,数据的数组形式就会赋值给$this->request->data。因为这个特性,并行处理 XML 和 POST 数据是无缝的:无需改动控制器或模型代码。所有需要的数据都会在 $this->request->data
中。
通常 REST 应用程序不但以多种数据格式输出内容,而且也接受不同格式的数据。在CakePHP 中, 有助于实现这一点。默认情况下,它会解码任何接收到的任何 POST/PUT 请求的 JSON/XML 输入数据,在$this->request->data 中提供该数据的数组版本。如果需要,也可以用RequestHandler::addInputType()
连入其它格式的反序列化。
如果默认的 REST 路由对应用程序不适用,可以用 Router::resourceMap()
方法改变。该方法让你可以设置 方法设置的默认路由。在使用该方法时需要设置 所有 要使用的默认值:
修改了默认的 resource map,以后对 mapResources()
的调用就会使用新值。
如果 创建的默认路由仍然不适用,可以用Router::connect()
方法定义一组自定义 REST 路由。connect()
方法让你可以为一个给定的网址定义一些不同的选项。欲知详情,请参考 一节。
2.5 新版功能.
你可以为 Router::mapResources()
方法在 $options
数组中指定connectOptions
键,来提供 方法使用的自定义设置:
- Router::mapResources('books', array(
- 'connectOptions' => array(
- 'routeClass' => 'ApiRoute',
- )