在 CakePHP 2.0 中请求和响应对象是新的。在之前的版本中,这些对象是用数组来表示的,相关的方法分散在RequestHandlerComponent、Router、 Dispatcher 和 Controller 中。请求包含的信息上没有认证对象。在 2.0 中,CakeRequest 和 CakeResponse 用于此目的。
CakeRequest 是 CakePHP 中的默认请求对象。它在请求数据中集成了一些咨询和交互特性。 CakeReqeust 建立在每个请求上,并以引用方式传递给使用请求数据的各个层。默认情况下,CakeRequest 赋值给 $this->request,并且在控制器、视图和助手中可用。 CakeRequest 执行的部分职责包括:
CakeRequest 提供了数种访问请求参数的接口。一是使用对象属性,二是使用数组索引,三是通过 $this->request->params:
1 $this->request->controller; 2 $this->request['controller']; 3 $this->request->params['controller'];
上面的所有形式都访问同一个值。提供参数的多种访问形式是为了已有应用程序的迁移。所有的 路由元素 都可以通过这种形式访问。
除了 路由元素 ,还经常需要访问 传递参数 和 命名参数。这此在请求对象中也都可用:
1 $this->request->controller; 2 $this->request['controller']; 3 $this->request->params['controller'];
上面提供了传递参数和命名参数的访问。这里有几个 CakePHP 内部使用的重要/有用的参数,这些参数也能在请求参数中找到:
query 参数可以用 CakeRequest::$query 读取:
1 // url 为 /posts/index?page=1&sort=title 2 $this->request->query['page']; 3 4 // 也可以用数组形式来访问 5 $this->request['url']['page']; // BC 存取器,将在未来版本中被废弃
你也可以直接访问 query 属性,或者以容错方式使用 CakeRequest::query() 读取 url query 数组。 任何不存在的键都返回空(null)值:
1 $foo = $this->request->query('value_that_does_not_exist'); 2 // $foo === null
访问 POST 数据
所有的 POST 数据都可以用 CakeRequest::$data 访问。包含 data 前缀的任意数据,其数据前缀都会被删除。例如:
1 // An input with a name attribute equal to 'data[MyModel][title]' is accessible at 2 $this->request->data['MyModel']['title'];
你也可以直接访问 data 属性,或者以容错方式使用 CakeRequest::data() 读取 data 数组。 任何不存在的键都返回空(null)值:
1 $foo = $this->request->data('Value.that.does.not.exist'); 2 // $foo == null
访问 PUT 或者 POST 数据
2.2 新版功能.
在创建 REST 服务时,常常在 PUT 和 DELETE 接受请求数据。2.2 版中,所有 application/x-www-form-urlencoded请求的主体数据将自动解析并且设置为 $this->data 的 PUT 和 DELETE 请求。如果你接收 JSON 或者 XML 数据,参看后文中如何访问这些请求的部分。
应用程序经常使用 REST 非 URL 编码的 post 体之间交换数据。你可以以任意格式使用 CakeRequest::input() 访问 input 数据。 通过提供解码功能,你可以接受反序列化形式的内容:
1 // 获取提交给 PUT/POST 动作的 JOSN 编码数据 2 $data = $this->request->input('json_decode');
自从某些反序列化方法在被调用时包含附加参数, CakeRequest::input() 也支持在附加参数中传递 json_decode 中的 ‘as array’ 参数,或者如果你想将 XML 转换成 DOM 文档对象:
1 // Get Xml encoded data submitted to a PUT/POST action 2 $data = $this->request->input('Xml::build', array('return' => 'domdocument'));
访问路径信息
CakeRequest 还提供关于应用程序路径的有用信息。 CakeRequest::$base 和 CakeRequest::$webroot 用于生成 url,并确定应用程序是否在一个子文件夹内。
以前使用 RequestHandlerComponent 检测各种请求条件。这些方法已经被移到 CakeRequest,并且新的接口(包含多个与回调兼容的用法):
1 $this->request->is('post'); 2 $this->request->isPost();
这些方法调用返回相同的值。眼下 RequestHandler 中的方法仍然可用,但是已经被废弃并可能会在后续版本中删除。你也可以轻易地扩展有效的请求探察器,使用 CakeRequest::addDetector() 创建新类型的探察器。你可以建立四种不同类型的探察器:
这有一些例子:
1 // 添加环境探察器。 2 $this->request->addDetector('post', array('env' => 'REQUEST_METHOD', 'value' => 'POST')); 3 4 // 添加模式值探察器。 5 $this->request->addDetector('iphone', array('env' => 'HTTP_USER_AGENT', 'pattern' => '/iPhone/i')); 6 7 // 添加选项探察器。 8 $this->request->addDetector('internalIp', array( 9 'env' => 'CLIENT_IP', 10 'options' => array('192.168.0.101', '192.168.0.100') 11 )); 12 13 // 添加回调探察器。可以是匿名函数或者定时调用。 14 $this->request->addDetector('awesome', array('callback' => function ($request) { 15 return isset($request->awesome); 16 }));
CakeRequest 还包括 CakeRequest::domain()、 CakeRequest::subdomains() 和 CakeRequest::host() 等方法用来帮助带有子域的应用程序,让生命更简单。
下面是一些可用的内置探察器:
由于``CakeRequest`` 提供的过去用于 RequestHandlerComponent 的一些特性,被要求反思如何仍然适合图片。对于 2.0, RequestHandlerComponent 扮演了一个甜心爹爹的角色。在 CakeRequest 提供的功能的顶层挂了一层糖。所谓的糖就是在 RequestHandlerComponent 范围内,基于内容的类型或者 ajax 切换布局和视图。这种分隔两类的工具和糖,让你更易于区分和选择你想要的和你需要的。
你可以使用 CakeRequest 反观关于请求的各种事物。除了探察器,你还能找到来自各种属性和方法的其他信息。
CakeRequest 压制 request 参数句柄和反视。
CakeRequest::domain($tldLength = 1)返回正在运行的应用程序的域。
CakeRequest::subdomains($tldLength = 1)以数组形式返回应用程序的子域。
CakeRequest::host()返回应用程序的主机。
CakeRequest::method()返回请求所用的 HTTP 方式。
CakeRequest::onlyAllow($methods)设置允许的 HTTP 方式,如果不匹配则抛出 MethodNotAllowexException。 这个伴随传送方法的 405 输出包含必须的 ‘Allow’ 头。 The 405 response will include the required ‘Allow’ header with the passed methods
2.3 新版功能.
CakeRequest::referer($local = false)返回请求的来源地址。
CakeRequest::clientIp($safe = true)返回当前访问者的 IP 地址。
CakeRequest::header($name)允许你使用此请求访问任意的 HTTP_* 头。
1 $this->request->header('User-Agent');
将返回此请求使用的用户代理。
从请求中获取 input 数据,并且可以向其传递一个解码函数。附加的参数中的解码函数可以被作为传递给 input()。
CakeRequest::data($name)提供 点表示法 访问请求数据。允许读取和修改请求数据,调用也可以串联在一起:
1 // 修改部分请求数据,以使你能够预一些表单域。 2 $this->request->data('Post.title', 'New post') 3 ->data('Comment.1.author', 'Mark'); 4 5 // 你也能读出数据。 6 $value = $this->request->data('Post.title');
提供 点表示法 访问 url query 数据:
1 // url 为 /posts/index?page=1&sort=title 2 $value = $this->request->query('page');
2.3 新版功能.
CakeRequest::is($type)检查一个请求是否符合某个标准。应用内置的匹配规则或者通过 CakeRequest::addDetector() 定义的任意附加规则。
CakeRequest::addDetector($name, $options)添加一个用于 is() 的探察器。更多信息参见 检查请求 。
CakeRequest::accepts($type = null)找出客户端接受的内容类型,或者检测它们接受的特定内容的类型。
获取全部类型
1 $this->request->accepts();
检查单个类型
1 $this->request->accepts('application/json');
获取客户端期望的全部语言,或者检测被接受的一个特定语言。
获取被接受的语言的列表
1 CakeRequest::acceptLanguage();
检测一个指定的被接受的语言
1 CakeRequest::acceptLanguage('es-es');
POST 数据的数组。作为防止错误提示的一种方式,你可以使用 CakeRequest::data() 读取这个属性。
property CakeRequest::$queryquery 字符串参数数组。
property CakeRequest::$params路由元素和请求参数数组。
property CakeRequest::$here返回当前请求的 uri。
property CakeRequest::$base应用程序的基路径,通常是 /,除非你的应用程序放在子目录中。
property CakeRequest::$webroot当前 web 根目录
CakeResponse 是 CakePHP 中的默认响应。它包含一些在应用程序中生成 HTTP 响应的特性和功能。它也有助于测试,因为它能被 mock/stub以允许你检查将要传输的头信息。 与 CakeRequest 类似, CakeResponse 整合了一些原来放在 Controller、RequestHandlerComponent 和 Dispatcher 中的方法。那些旧方法已经被废弃,转而使用CakeResponse.。 CakeResponse 提供了一个接口,这个接口打包了与下面的任务相关的公用响应:
CakePHP 默认使用 CakeResponse。 CakeResponse 对于使用类是灵活透明的。不过如果你需要在应用程序的特定类中替换它,你使用自己的类覆盖或替换 CakeResponse 。通过替换在 index.php 中使用的 CakePHPResponse。
这会使你的应用程序中的所有控制器都用 CustomResponse 代替 CakeResponse。 你也可以在控制器中设置 $this->response 来替换 response 实例。 在测试过程中覆盖这个 response 对象很有用,它允许你 stub 与 header() 一起工作的方法。 更多的信息请参见 CakeResponse 与测试 一节。
你可以使用 CakeResponse::type() 控制应用程序响应的 内容类型(Content-Type)。如果你的应用程序需要处理没有内置在 CakeResponse 中的内容类型,你还可以使用 type() 映射它们:
1 // 添加 vCard 类型 2 $this->response->type(array('vcf' => 'text/v-card')); 3 4 // 将响应的 Content-Type 设置为 vcard. 5 $this->response->type('vcf');
通常你将会在控制器的 beforeFilter 回调中映射附加的内容类型,如果需要,你可以利用 RequestHandlerComponent的自动视图切换功能。
有时候你需要为请求发送文件作为对其的响应。 在 2.3 版之前你可以使用 媒体视图 来实现。 在 2.3 版,MediaView 被废弃,现在你可以使用 CakeResponse::file() 传送文件来响应:
1 public function sendFile($id) { 2 $file = $this->Attachment->getFile($id); 3 $this->response->file($file['path']); 4 }
上面显示的例子要求向方法传送文件路径。 如果它是列在 CakeReponse::$_mimeTypes 中的已知文件类型,Cake 将发送适当的内容类型头信息。你也可以在调用 CakeResponse::file() 之前使用 CakeResponse::type() 方法添加新的文件类型。
如果你只想让文件显示在浏览器中,禁止文件被下载,可以指定如下选项:
1 $this->response->file($file['path'], array('download' => true, 'name' => 'foo'));
设置 header
设置 headers 使用的是 CakeResponse::header() 方法。 它能以不同的参数配置调用:
1 // 设置单个 header 2 $this->response->header('Location', 'http://example.com'); 3 4 // 设置多个 headers 5 $this->response->header(array('Location' => 'http://example.com', 'X-Extra' => 'My header')); 6 $this->response->header(array('WWW-Authenticate: Negotiate', 'Content-type: application/pdf'));
一个 header 被设置多次,将只保留最后一次的设置,就像普通的 header 调用一样。当调用CakeResponse::header() 时,Header 并没有发送。它们在响应被真实的发送之前只是被缓冲了。
有时你需要禁止浏览器缓存控制器动作的结果。 CakeResponse::disableCache() 就是用来干这个的::
1 public function index() { 2 // do something. 3 $this->response->disableCache(); 4 }
警告
在 SSL 域中使用与下载文件一起使用 disableCache() 传送文件到 Internet Explorer 可能引起错误。
你也可以使用 CakeResponse::cache() 告诉客户端你想要它们缓存响应:
1 public function index() { 2 //do something 3 $this->response->cache('-1 minute', '+5 days'); 4 }
上面的代码告诉客户端缓存响应结果5天,希望提高访客在速度方面的体验。cache() 的第一个参数是最后编辑(Last-Modifield)的值。过期(Expires)和最大年龄(Max-age)参数是以秒为单位的。还有,缓存控制(Cache-Control)设置为 public。
提高应用程序的访问速度的一个又好又容易的办法是使用 HTTP 缓存。 在这种模式下,你只需要通过设置几个 header (如编辑时间、响应实体及其它)来帮助客户端决定是否使用响应的缓存副本。
反对使用代码逻辑处理 缓存和在数据改变时失效(刷新),HTTP 的过期和校验两种模式常常比自己管理缓存更简单。
除了 CakeResponse::cache() ,你还可以使用另外一些方法实现 HTTP 缓存头来利用浏览器或反向代理缓存。
2.1 新版功能.
在过期模式下,header 包括多个能够使浏览器或代理使用缓存内容的标志。一个 Cache-Control header 如下:
1 Cache-Control: private, max-age=3600, must-revalidate
CakeResponse 类及一些产生最终有效的 Cache-Control header 工具方法帮助你设置这些头信息。其中的第一个是CakeResponse::sharable() 方法, 它标志一个响应是否考虑在不同的用户或者客户端共享。 此方法实际控制 header 的 public 或者 private 部分。将响应设置成 private 标志着它的全部或部分是设计给单个用户的。要共享缓存需要将 control 指令设置为 public。
此方法的第二个参数用于指定缓存的 Max-age ,它声明响应在多少秒后过期。
1 public function view() { 2 ... 3 // set the Cache-Control as public for 3600 seconds 4 $this->response->sharable(true, 3600); 5 } 6 7 public function my_data() { 8 ... 9 // set the Cache-Control as private for 3600 seconds 10 $this->response->sharable(false, 3600); 11 }
CakeResponse 公开了设定 Cache-Control header 中的每个组件的独立方法。
2.1 新版功能.
还是在过期模式下,你可以设置 Expires header,它指定响应在指定的日期/时间之后过期,时间和日期为 HTTP 规范格式。这个 header 可以使用 CakeResponse::expires() 方法设置:
1 public function view() { 2 $this->response->expires('+5 days'); 3 }