热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

CakePHP2.xCookBook中文版第五章控制器之请求和响应对象

比较请求对象的cacheheader和响应的cacheheader,确定其是否仍然有效。如果仍然有效,则删除所有响应内容,并传送304NotModifiedheader。

请求和响应对象

在 CakePHP 2.0 中请求和响应对象是新的。在之前的版本中,这些对象是用数组来表示的,相关的方法分散在RequestHandlerComponentRouter、 Dispatcher 和 Controller 中。请求包含的信息上没有认证对象。在 2.0 中,CakeRequest 和 CakeResponse 用于此目的。

CakeRequest

CakeRequest 是 CakePHP 中的默认请求对象。它在请求数据中集成了一些咨询和交互特性。 CakeReqeust 建立在每个请求上,并以引用方式传递给使用请求数据的各个层。默认情况下,CakeRequest 赋值给 $this->request,并且在控制器、视图和助手中可用。 CakeRequest 执行的部分职责包括:

  • 将 GET、POST 和 FILES 数组处理成你熟悉的数据结构。
  • 为请求提供相关的自省环境。类似于头信息传送、客户端 IP 地址、运行应用程序的服务器的子域/域信息等。
  • 提供以数组成员/对象属性两种形式访问请求参数。

访问请求对象

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 内部使用的重要/有用的参数,这些参数也能在请求参数中找到:

  • plugin 处理请求的插件,没有插件时为空(null)。
  • controller 处理当前请求的控制器。
  • action 处理当前请求的动作。
  • prefix 当前动作的前缀。更多信息参见 前置路由 。
  • bare 在请求来自 requestAction() 并且包含 bare 选项时出现。Bare 请求没有要渲染的布局。
  • requested 当动作来自 requestAction 时出现并被设置为 true。

访问 query 参数

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 数据,参看后文中如何访问这些请求的部分。

访问 XML 或者 JSON 数据

应用程序经常使用 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() 创建新类型的探察器。你可以建立四种不同类型的探察器:

  • 环境值对比 - 一个环境值对比,对比来自 env() 的值和环境变量中已知的值是否来检测所提供的值是否相等。
  • 模式值对比 - 模式值对比允许你对比来自 env() 的值和正则表达式。
  • 基于选项的对比 - 基于选项的对比使用一个选项列表建立一个正则表达式。后续调用加入一个已经定义选项的探察器来合并选项。
  • 回调探察器 - 回调发现都允许你提供一个 ‘回调’ 类型来处理检测。回调将接受请求对象作为它的唯一参数。

这有一些例子:

 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() 等方法用来帮助带有子域的应用程序,让生命更简单。

下面是一些可用的内置探察器:

  • is('get') 检测当前的请求是否是一个 GET。
  • is('put') 检测当前的请求是否是一个 PUT.
  • is('post') 检测当前的请求是否是一个 POST.
  • is('delete') 检测当前的请求是否是一个 DELETE.
  • is('head') 检测当前的请求是否是一个 HEAD.
  • is('options') C检测当前的请求是否是 OPTIONS.
  • is('ajax') 检测当前的请求是否是来自 X-Requested-with = XmlHttpRequest.
  • is('ssl') 检测当前的请求是否经过 SSL
  • is('flash') 检测当前的请求是否有一个 Flash 用户代理
  • is('mobile') 检测当前的请求是否来自移动代理。

CakeRequest 和 RequestHandlerComponent

由于``CakeRequest`` 提供的过去用于 RequestHandlerComponent 的一些特性,被要求反思如何仍然适合图片。对于 2.0, RequestHandlerComponent 扮演了一个甜心爹爹的角色。在 CakeRequest 提供的功能的顶层挂了一层糖。所谓的糖就是在 RequestHandlerComponent 范围内,基于内容的类型或者 ajax 切换布局和视图。这种分隔两类的工具和糖,让你更易于区分和选择你想要的和你需要的。

与其它层面的请求互动

你可以使用 CakeRequest 反观关于请求的各种事物。除了探察器,你还能找到来自各种属性和方法的其他信息。

  • $this->request->webroot 表示 web 根目录。
  • $this->request->base 表示基目录。
  • $this->request->here 表示当前请求的完整地址。
  • $this->request->query 包含 query 字符串参数。

CakeRequest API

class 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');

将返回此请求使用的用户代理。

CakeRequest::input($callback[$options])

从请求中获取 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');


CakeRequest::query($name)

提供 点表示法 访问 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');


static CakeRequest::acceptLanguage($language = null)

获取客户端期望的全部语言,或者检测被接受的一个特定语言。

获取被接受的语言的列表

1 CakeRequest::acceptLanguage();

检测一个指定的被接受的语言

1 CakeRequest::acceptLanguage('es-es');


property CakeRequest::$data

POST 数据的数组。作为防止错误提示的一种方式,你可以使用 CakeRequest::data() 读取这个属性。

property CakeRequest::$query

query 字符串参数数组。

property CakeRequest::$params

路由元素和请求参数数组。

property CakeRequest::$here

返回当前请求的 uri。

property CakeRequest::$base

应用程序的基路径,通常是 /,除非你的应用程序放在子目录中。

property CakeRequest::$webroot

当前 web 根目录

CakeResponse

CakeResponse 是 CakePHP 中的默认响应。它包含一些在应用程序中生成 HTTP 响应的特性和功能。它也有助于测试,因为它能被 mock/stub以允许你检查将要传输的头信息。 与 CakeRequest 类似, CakeResponse 整合了一些原来放在 ControllerRequestHandlerComponent 和 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 缓存微调

提高应用程序的访问速度的一个又好又容易的办法是使用 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 }
        
        
    
推荐阅读
  • 本文详细介绍了如何手动编写兼容IE的Ajax函数,以及探讨了跨域请求的实现方法和原理,包括JSONP和服务器端设置HTTP头部等技术。 ... [详细]
  • 本文探讨了如何在JavaScript中调用PHP函数及实现两者之间的有效交互,包括通过AJAX请求、动态生成JavaScript代码等方法。 ... [详细]
  • 解决fetch上传图片至微信公众号H5页面的问题
    在近期的一个项目需求中,需要在微信公众号内嵌入H5页面,并实现用户通过该页面上传图片的功能,包括拍摄新照片或从已有相册中选择。前端开发中采用了fetch API进行接口调用,但遇到了上传图片时数据无法正确传递的问题。 ... [详细]
  • 本文详细记录了《PHP与MySQL Web开发》第一章的学习心得,特别关注了PHP的基本构成元素、标记风格、编程注意事项及表单处理技巧等内容。 ... [详细]
  • 致信息安全爱好者的成长指南
    本文旨在为信息安全爱好者提供一份详尽的成长指南,涵盖从学习心态调整到具体技能提升的各个方面。 ... [详细]
  • 本文探讨了为何采用RESTful架构及其优势,特别是在现代Web应用开发中的重要性。通过前后端分离和统一接口设计,RESTful API能够提高开发效率,支持多种客户端,并简化维护。 ... [详细]
  • 本文介绍如何使用 jQuery 的 AJAX 方法从服务器获取 JSON 数据,并通过遍历这些数据来创建包含公司及其产品信息的数组。 ... [详细]
  • 深入理解FastDFS
    FastDFS是一款高效、简洁的分布式文件系统,广泛应用于互联网应用中,用于处理大量用户上传的文件,如图片、视频等。本文探讨了FastDFS的设计理念及其如何通过独特的架构设计提高性能和可靠性。 ... [详细]
  • 消息传递这一应用广泛存在于各个网站中,这个功能也是一个网站必不可少的。本文主要介绍了php中Redis的应用--消息传递。下面跟着小编一起来看下吧阅读目录1、摘要2、实现方法3、一 ... [详细]
  • 本文介绍了如何通过安装 VirtualBox 和 Vagrant 来快速搭建和管理虚拟机环境。我们将详细探讨如何选择合适的 Box 镜像,以及如何高效地下载、添加和管理这些镜像。 ... [详细]
  • HTML中用于创建表单的标签是什么
    本文将详细介绍HTML中用于创建表单的标签及其基本用法,包括表单的主要特性和常用的属性设置。如果您正在学习HTML或需要了解如何在网页中添加表单,这将是一个很好的起点。 ... [详细]
  • Elasticsearch基础操作指南:使用Postman进行数据管理
    本文将介绍如何利用Postman工具执行基本的日志写入和数据管理操作。通过本教程,您将了解如何连接至Elasticsearch服务,创建索引,存储及检索数据。 ... [详细]
  • 本文详细介绍了如何利用Apple Pay的功能将门禁卡添加至iPhone或Apple Watch,适用于多种门禁系统,包括在线和离线模式。 ... [详细]
  • 应用程序配置详解
    本文介绍了配置文件的关键特性及其在不同场景下的应用,重点探讨了Machine.Config和Web.Config两种主要配置文件的用途和配置方法。文章还详细解释了如何利用XML格式的配置文件来调整应用程序的行为,包括自定义配置、错误处理、身份验证和授权设置。 ... [详细]
  • 使用 NDB 提升 Node.js 应用调试体验
    本文介绍了由 Google Chrome 实验室推出的新一代 Node.js 调试工具 NDB,旨在为开发者提供更加高效和便捷的调试解决方案。 ... [详细]
author-avatar
薇薇VS安安北_396
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有