요청
요청:
애플리케이션 요청은 요청 매개변수(번역자 참고 사항: 일반적으로 GET 매개변수 또는 POST 매개변수), HTTP 헤더, 쿠키 및 기타 정보와 같은 정보를 제공하는 yiiwebRequest 개체로 표시됩니다. 기본적으로 특정 요청에 대해 요청 애플리케이션 구성요소 애플리케이션 구성요소(yiiwebRequest 클래스의 인스턴스)를 통해 해당 요청 객체에 대한 액세스를 얻을 수 있습니다. 이 장에서는 애플리케이션에서 이 구성 요소를 사용하는 방법을 소개합니다.
1. 요청 매개변수
요청 매개변수를 얻으려면 요청 구성 요소의 yiiwebRequest::get() 메서드와 yiiwebRequest::post() 메서드를 호출하면 됩니다. 각각 $_GET 및 $_POST 값을 반환합니다. 예를 들어
$request = Yii::$app->request; $get = $request->get(); // 等价于: $get = $_GET; $id = $request->get('id'); // 等价于: $id = isset($_GET['id']) ? $_GET['id'] : null; $id = $request->get('id', 1); // 等价于: $id = isset($_GET['id']) ? $_GET['id'] : 1; $post = $request->post(); // 等价于: $post = $_POST; $name = $request->post('name'); // 等价于: $name = isset($_POST['name']) ? $_POST['name'] : null; $name = $request->post('name', ''); // 等价于: $name = isset($_POST['name']) ? $_POST['name'] : '';
주의사항: $_GET, $_POST에 직접 접근하는 것보다 위와 같이 요청 컴포넌트를 통해 요청 매개변수를 얻는 것이 좋습니다. 이렇게 하면 모의 요청 구성 요소를 생성하기 위해 데이터를 가짜로 만들 수 있으므로 테스트 사례를 더 쉽게 작성할 수 있습니다.
RESTful API를 구현할 때 PUT, PATCH 또는 기타 요청 방법을 통해 제출된 매개변수를 가져와야 하는 경우가 많습니다. yiiwebRequest::getBodyParam() 메소드를 호출하여 이러한 매개변수를 얻을 수 있습니다. 예를 들어
$request = Yii::$app->request; // 返回所有参数 $params = $request->bodyParams; // 返回参数 "id" $param = $request->getBodyParam('id');
정보: GET 매개변수와 달리 POST, PUT, PATCH 등 제출된 매개변수는 요청 본문에 전송됩니다. 위에서 설명한 방법을 통해 이러한 매개변수에 액세스하면 요청 구성요소가 이러한 매개변수를 구문 분석합니다. yiiwebRequest::parsers 속성을 구성하여 이러한 매개변수를 구문 분석하는 방법을 사용자 정의할 수 있습니다.
2. 요청 방법
Yii::$app->request->method 표현식을 통해 현재 요청에 사용되는 HTTP 메소드를 얻을 수 있습니다. 현재 요청이 특정 유형인지 여부를 감지하기 위해 일련의 부울 속성도 여기에 제공됩니다. 예를 들어
$request = Yii::$app->request; if ($request->isAjax) { /* 该请求是一个 AJAX 请求 */ } if ($request->isGet) { /* 请求方法是 GET */ } if ($request->isPost) { /* 请求方法是 POST */ } if ($request->isPut) { /* 请求方法是 PUT */ }
3. 요청 URL
요청 구성 요소는 현재 요청된 URL을 감지하는 다양한 방법을 제공합니다.
요청한 URL이 http://example.com/admin/index.php/product?id=100이라고 가정하면 아래와 같이 URL의 다양한 부분을 얻을 수 있습니다.
4.HTTP 헤더
yiiwebRequest::headers 속성에서 반환된 yiiwebHeaderCollection을 통해 HTTP 헤더 정보를 얻을 수 있습니다. 예를 들어
// $headers 是一个 yii\web\HeaderCollection 对象 $headers = Yii::$app->request->headers; // 返回 Accept header 值 $accept = $headers->get('Accept'); if ($headers->has('User-Agent')) { /* 这是一个 User-Agent 头 */ }
요청 구성 요소는 다음을 포함하여 일반 헤더에 빠르게 액세스할 수 있는 방법도 제공합니다.
애플리케이션이 여러 언어를 지원하고 최종 사용자가 선호하는 언어로 페이지를 표시하려는 경우 언어 협상 방법 yiiwebRequest::getPreferredLanguage()를 사용할 수 있습니다. 이 메소드는 yiiwebRequest::acceptableLanguages를 사용하여 애플리케이션에서 지원되는 언어 목록을 비교 및 필터링하고 가장 적합한 언어를 반환합니다.
팁: yiifiltersContentNegotiator 필터를 사용하여 응답에 사용해야 하는 콘텐츠 유형과 언어를 동적으로 결정할 수도 있습니다. 이 필터는 위에서 설명한 콘텐츠 협상 속성과 메서드를 구현합니다.
5. 고객정보
yiiwebRequest::userHost 및 yiiwebRequest::userIP를 통해 각각 호스트 이름과 클라이언트 IP 주소를 얻을 수 있습니다(예:
$userHost = Yii::$app->request->userHost; $userIP = Yii::$app->request->userIP;
二、响应(Responses)
响应:
当应用完成处理一个请求后, 会生成一个yii\web\Response响应对象并发送给终端用户 响应对象包含的信息有HTTP状态码,HTTP头和主体内容等, 网页应用开发的最终目的本质上就是根据不同的请求构建这些响应对象。
在大多是情况下主要处理继承自 yii\web\Response 的 response 应用组件, 尽管如此,Yii也允许你创建你自己的响应对象并发送给终端用户,这方面后续会阐述。
在本节,将会描述如何构建响应和发送给终端用户。
1.状态码
构建响应时,最先应做的是标识请求是否成功处理的状态,可通过设置 yii\web\Response::statusCode 属性,该属性使用一个有效的HTTP 状态码。例如,为标识处理已被处理成功, 可设置状态码为200,如下所示:
Yii::$app->response->statusCode = 200;
尽管如此,大多数情况下不需要明确设置状态码,因为 yii\web\Response::statusCode 状态码默认为200, 如果需要指定请求失败,可抛出对应的HTTP异常,如下所示:
throw new \yii\web\NotFoundHttpException;
当错误处理器 捕获到一个异常,会从异常中提取状态码并赋值到响应, 对于上述的 yii\web\NotFoundHttpException 对应HTTP 404状态码,以下为Yii预定义的HTTP异常:
如果想抛出的异常不在如上列表中,可创建一个yii\web\HttpException异常,带上状态码抛出,如下:
throw new \yii\web\HttpException(402);
2.HTTP 头部
可在 response 组件中操控yii\web\Response::headers来发送HTTP头部信息,例如:
$headers = Yii::$app->response->headers; // 增加一个 Pragma 头,已存在的Pragma 头不会被覆盖。 $headers->add('Pragma', 'no-cache'); // 设置一个Pragma 头. 任何已存在的Pragma 头都会被丢弃 $headers->set('Pragma', 'no-cache'); // 删除Pragma 头并返回删除的Pragma 头的值到数组 $values = $headers->remove('Pragma');
补充: 头名称是大小写敏感的,在yii\web\Response::send()方法调用前新注册的头信息并不会发送给用户。
3.响应主体
大多是响应应有一个主体存放你想要显示给终端用户的内容。
如果已有格式化好的主体字符串,可赋值到响应的yii\web\Response::content属性,例如:
Yii::$app->response->content = 'hello world!';
如果在发送给终端用户之前需要格式化,应设置 yii\web\Response::format 和 yii\web\Response::data 属性,yii\web\Response::format 属性指定yii\web\Response::data中数据格式化后的样式,例如:
$response = Yii::$app->response; $response->format = \yii\web\Response::FORMAT_JSON; $response->data = ['message' => 'hello world'];
Yii支持以下可直接使用的格式,每个实现了yii\web\ResponseFormatterInterface 类, 可自定义这些格式器或通过配置yii\web\Response::formatters 属性来增加格式器。
上述响应主体可明确地被设置,但是在大多数情况下是通过 操作 方法的返回值隐式地设置,常用场景如下所示:
public function actionIndex() { return $this->render('index'); }
上述的 index 操作返回 index 视图渲染结果,返回值会被 response 组件格式化后发送给终端用户。
因为响应格式默认为yii\web\Response::FORMAT_HTML, 只需要在操作方法中返回一个字符串, 如果想使用其他响应格式,应在返回数据前先设置格式,例如:
public function actionInfo() { \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; return [ 'message' => 'hello world', 'code' => 100, ]; }
如上所述,触雷使用默认的 response 应用组件,也可创建自己的响应对象并发送给终端用户,可在操作方法中返回该响应对象,如下所示:
public function actionInfo() { return \Yii::createObject([ 'class' => 'yii\web\Response', 'format' => \yii\web\Response::FORMAT_JSON, 'data' => [ 'message' => 'hello world', 'code' => 100, ], ]); }
注意: 如果创建你自己的响应对象,将不能在应用配置中设置 response 组件,尽管如此, 可使用 依赖注入 应用通用配置到你新的响应对象。
4.浏览器跳转
浏览器跳转依赖于发送一个Location HTTP 头,因为该功能通常被使用,Yii提供对它提供了特别的支持。
可调用yii\web\Response::redirect() 方法将用户浏览器跳转到一个URL地址,该方法设置合适的 带指定URL的 Location 头并返回它自己为响应对象,在操作的方法中,可调用缩写版yii\web\Controller::redirect(),例如:
public function actionOld() { return $this->redirect('http://example.com/new', 301); }
在如上代码中,操作的方法返回redirect() 方法的结果,如前所述,操作的方法返回的响应对象会被当总响应发送给终端用户。
除了操作方法外,可直接调用yii\web\Response::redirect() 再调用 yii\web\Response::send() 方法来确保没有其他内容追加到响应中。
\Yii::$app->response->redirect('http://example.com/new', 301)->send();
补充: yii\web\Response::redirect() 方法默认会设置响应状态码为302,该状态码会告诉浏览器请求的资源 临时 放在另一个URI地址上,可传递一个301状态码告知浏览器请求的资源已经 永久 重定向到新的URId地址。
如果当前请求为AJAX 请求,发送一个 Location 头不会自动使浏览器跳转,为解决这个问题, yii\web\Response::redirect() 方法设置一个值为要跳转的URL的X-Redirect 头, 在客户端可编写JavaScript 代码读取该头部值然后让浏览器跳转对应的URL。
补充: Yii 配备了一个yii.js JavaScript 文件提供常用JavaScript功能,包括基于X-Redirect头的浏览器跳转, 因此,如果你使用该JavaScript 文件(通过yii\web\YiiAsset 资源包注册),就不需要编写AJAX跳转的代码。
5.发送文件
和浏览器跳转类似,文件发送是另一个依赖指定HTTP头的功能,Yii提供方法集合来支持各种文件发送需求,它们对HTTP头都有内置的支持。
这些方法都将响应对象作为返回值,如果要发送的文件非常大,应考虑使用 yii\web\Response::sendStreamAsFile() 因为它更节约内存,以下示例显示在控制器操作中如何发送文件:
public function actionDownload() { return \Yii::$app->response->sendFile('path/to/file.txt'); }
如果不是在操作方法中调用文件发送方法,在后面还应调用 yii\web\Response::send() 没有其他内容追加到响应中。
\Yii::$app->response->sendFile('path/to/file.txt')->send();
一些浏览器提供特殊的名为X-Sendfile的文件发送功能,原理为将请求跳转到服务器上的文件, Web应用可在服务器发送文件前结束,为使用该功能,可调用yii\web\Response::xSendFile(), 如下简要列出一些常用Web服务器如何启用X-Sendfile 功能:
Apache: X-Sendfile Lighttpd v1.4: X-LIGHTTPD-send-file Lighttpd v1.5: X-Sendfile Nginx: X-Accel-Redirect Cherokee: X-Sendfile and X-Accel-Redirect
6.发送响应
在yii\web\Response::send() 方法调用前响应中的内容不会发送给用户,该方法默认在yii\base\Application::run() 结尾自动调用,尽管如此,可以明确调用该方法强制立即发送响应。
yii\web\Response::send() 方法使用以下步骤来发送响应:
一旦yii\web\Response::send() 方法被执行后,其他地方调用该方法会被忽略, 这意味着一旦响应发出后,就不能再追加其他内容。
如你所见yii\web\Response::send() 触发了几个实用的事件,通过响应这些事件可调整或包装响应。