IncomingRequest 类

IncomingRequest 类提供了客户端(如浏览器)HTTP 请求的面向对象表示。 除了下文列出的方法外,此类还继承并可访问 RequestMessage 类的所有方法。

访问请求

如果当前类继承自 CodeIgniter\Controller,则 Request 类的实例已自动填充,并可通过类属性访问:

<?php

namespace App\Controllers;

use CodeIgniter\Controller;

class UserController extends Controller
{
    public function index()
    {
        if ($this->request->isAJAX()) {
            // ...
        }
    }
}

如果不在控制器内,但仍需访问应用程序的 Request 对象,可通过 Services 类 获取副本:

<?php

$request = service('request');

不过,如果类不是控制器,建议将 Request 作为依赖项传入并存为类属性:

<?php

namespace App\Libraries;

use CodeIgniter\HTTP\RequestInterface;

class SomeClass
{
    protected $request;

    public function __construct(RequestInterface $request)
    {
        $this->request = $request;
    }
}

$someClass = new SomeClass(service('request'));

判断请求类型

请求可能有多种类型,包括 AJAX 请求或命令行请求。可使用 isAJAX()isCLI() 方法进行检查:

<?php

// Check for AJAX request.
if ($request->isAJAX()) {
    // ...
}

// Check for CLI Request
if ($request->isCLI()) {
    // ...
}

备注

isAJAX() 方法依赖于 X-Requested-With 标头。在某些情况下,通过 JavaScript(如 fetch)发起的 XHR 请求默认不会发送该标头。请参阅 AJAX 请求 章节了解如何解决此问题。

is()

Added in version 4.3.0.

自 v4.3.0 起,可使用 is() 方法。该方法接受 HTTP 方法、'ajax''json',并返回布尔值。

备注

虽然 HTTP 方法区分大小写,但此参数不区分大小写。

<?php

// Checks HTTP methods. Returns boolean.
$request->is('get');
$request->is('post');
$request->is('put');
$request->is('delete');
$request->is('head');
$request->is('patch');
$request->is('options');

// Checks if it is an AJAX request. The same as `$request->isAJAX()`.
$request->is('ajax');

// Checks if it is a JSON request.
$request->is('json');

getMethod()

可使用 getMethod() 方法检查此请求代表的 HTTP 方法:

<?php

// Returns 'POST'
$method = $request->getMethod();

HTTP 方法区分大小写。按照惯例,标准方法均由大写 US-ASCII 字母定义。

备注

v4.5.0 之前,该方法默认返回小写字符串(如 'get''post' 等),但这其实是一个 Bug。

可通过 strtolower() 封装调用以获取小写版本:

// 返回 'get'
$method = strtolower($request->getMethod());

还可使用 isSecure() 方法检查是否通过 HTTPS 连接发起请求:

<?php

if (! $request->isSecure()) {
    force_https();
}

获取输入数据

可通过 Request 对象从 $_GET$_POST$_COOKIE$_SERVER$_ENV 中获取输入。 数据不会被自动过滤,将返回请求传入的原始输入数据。

备注

使用全局变量并非良好实践。原则上应避免使用,建议使用 Request 对象的方法。

使用这些方法而非直接访问(如 $_POST['something'])的主要优势在于:如果项不存在将返回 null,且支持数据过滤。这使得在使用数据前无需先测试其是否存在。换言之,通常可能需要这样做:

<?php

$something = $_POST['foo'] ?? null;

使用 CodeIgniter 的内置方法,只需:

<?php

$something = $request->getPost('foo');

获取数据

getGet()

getGet() 方法将从 $_GET 中获取数据。

  • $request->getGet()

getPost()

getPost() 方法将从 $_POST 中获取数据。

  • $request->getPost()

getCookie()

getCookie() 方法将从 $_COOKIE 中获取数据。

  • $request->getCookie()

getServer()

getServer() 方法将从 $_SERVER 中获取数据。

  • $request->getServer()

getPostGet()

此外,还有一些实用方法可从 $_GET$_POST 中检索信息,并支持控制搜索顺序:

  • $request->getPostGet() - 先检查 $_POST,再检查 $_GET

getGetPost()

  • $request->getGetPost() - 先检查 $_GET,再检查 $_POST

getVar()

重要

此方法仅为了向后兼容而存在。请勿在新项目中使用。即使已经在用,也建议换用其他更合适的方法。

getVar() 方法将从 $_REQUEST 中获取数据,因此会返回来自 $_GET$_POST$_COOKIE 的任何数据(取决于 php.ini 中的 request-order)。

警告

如果只想验证 POST 数据,请勿使用 getVar()。较新的值会覆盖旧值。如果在 request-order 中将 "C" 设置在 "P" 之后,同名的 Cookie 值可能会覆盖 POST 值。

备注

如果传入请求的 Content-Type 标头设为 application/jsongetVar() 方法将返回 JSON 数据而非 $_REQUEST 数据。

获取 JSON 数据

可使用 getJSON()php://input 的内容作为 JSON 流获取。

备注

此方法无法检查传入数据是否为有效的 JSON,仅应在确定预期为 JSON 时使用。

<?php

$json = $request->getJSON();

默认情况下,该方法将 JSON 数据中的所有对象作为对象返回。如果希望将其转换为关联数组,请将第一个参数设为 true

第二和第三个参数分别对应 PHP 函数 json_decode()$depth$flags 参数。

从 JSON 获取特定数据

通过向 getJsonVar() 传入变量名,可获取 JSON 流中的特定数据;也可使用“点”语法深入 JSON 获取非根级别的数据。

<?php

/*
 * With a request body of:
 * {
 *     "foo": "bar",
 *     "fizz": {
 *         "buzz": "baz"
 *     }
 * }
 */

$data = $request->getJsonVar('foo');
// $data = "bar"

$data = $request->getJsonVar('fizz.buzz');
// $data = "baz"

如果希望结果是关联数组而非对象,可在第二个参数传入 true:

<?php

// With the same request as above
$data = $request->getJsonVar('fizz');
// $data->buzz = "baz"

$data = $request->getJsonVar('fizz', true);
// $data = ["buzz" => "baz"]

备注

有关“点”语法的更多信息,请参阅 数组 辅助函数中 dot_array_search() 的文档。

获取原始数据(PUT、PATCH、DELETE)

最后,可使用 getRawInput()php://input 的内容作为原始流获取:

<?php

$data = $request->getRawInput();

这将检索数据并将其转换为数组。如下所示:

<?php

var_dump($request->getRawInput());

/*
 * Outputs:
 * [
 *     'Param1' => 'Value1',
 *     'Param2' => 'Value2',
 * ]
 */

也可使用 getRawInputVar() 从原始流中获取特定变量并进行过滤。

<?php

// When the request body is 'foo=one&bar=two&baz[]=10&baz[]=20'
var_dump($request->getRawInputVar('bar'));
// Outputs: two

// foo=one&bar=two&baz[]=10&baz[]=20
var_dump($request->getRawInputVar(['foo', 'bar']));
/*
 * Outputs:
 * [
 *      'foo' => 'one',
 *      'bar' => 'two'
 * ]
 */

// foo=one&bar=two&baz[]=10&baz[]=20
var_dump($request->getRawInputVar('baz'));
/*
 * Outputs:
 * [
 *      '10',
 *      '20'
 * ]
 */

// foo=one&bar=two&baz[]=10&baz[]=20
var_dump($request->getRawInputVar('baz.0'));
// Outputs: 10

过滤输入数据

为了维护应用程序安全,应在访问所有输入时进行过滤。可将过滤器类型作为这些方法的第二个参数传入。过滤功能使用原生的 filter_var() 函数。关于有效过滤器类型的列表,请参考 PHP 手册中的 可用过滤器列表

过滤 POST 变量示例如下:

<?php

$email = $request->getPost('email', FILTER_SANITIZE_EMAIL);

getJSON()getRawInput() 外,上述所有方法均支持在第二个参数中传入过滤器类型。

获取标头

可使用 headers() 方法访问随请求发送的所有标头。该方法返回一个数组,键为标头名称,值为 CodeIgniter\HTTP\Header 实例:

<?php

var_dump($request->headers());

/*
 * Outputs:
 * [
 *     'Host'          => CodeIgniter\HTTP\Header,
 *     'Cache-Control' => CodeIgniter\HTTP\Header,
 *     'Accept'        => CodeIgniter\HTTP\Header,
 * ]
 */

如果只需要单个标头,可将名称传入 header() 方法。如果该标头存在,将以不区分大小写的方式获取指定的标头对象;否则返回 null

<?php

// these are all equivalent
$host = $request->header('host');
$host = $request->header('Host');
$host = $request->header('HOST');

可随时使用 hasHeader() 检查此请求中是否存在某个标头:

<?php

if ($request->hasHeader('DNT')) {
    // Don't track something...
}

如果需要以字符串形式获取一行内的所有标头值,可使用 getHeaderLine() 方法:

<?php

// Accept-Encoding: gzip, deflate, sdch
echo 'Accept-Encoding: ' . $request->getHeaderLine('accept-encoding');

如果需要包含名称和值的完整标头字符串,直接将标头转换为字符串即可:

<?php

echo (string) $header;

请求 URL

可通过 $request->getUri() 方法获取代表当前请求 URI 的 URI 对象。将此对象转换为字符串可获取当前请求的完整 URL:

<?php

$uri = (string) $request->getUri();

该对象提供了获取请求中任何部分的完整能力:

<?php

$uri = $request->getUri();

echo $uri->getScheme();         // http
echo $uri->getAuthority();      // snoopy:password@example.com:88
echo $uri->getUserInfo();       // snoopy:password
echo $uri->getHost();           // example.com
echo $uri->getPort();           // 88
echo $uri->getPath();           // /path/to/page
echo $uri->getRoutePath();      // path/to/page
echo $uri->getQuery();          // foo=bar&bar=baz
print_r($uri->getSegments());   // Array ( [0] => path [1] => to [2] => page )
echo $uri->getSegment(1);       // path
echo $uri->getTotalSegments();  // 3

可使用 getRoutePath() 处理当前 URI 字符串(相对于 baseURL 的路径)。

备注

getRoutePath() 方法自 v4.4.0 起可用。在 v4.4.0 之前,getPath() 方法返回相对于 baseURL 的路径。

上传文件

可通过 $request->getFiles() 获取所有上传文件的信息,该方法返回 CodeIgniter\HTTP\Files\UploadedFile 实例数组。这有助于简化上传文件的处理,并采用最佳实践以降低安全风险。

<?php

$files = $request->getFiles();

详情请参阅 处理上传文件

可根据 HTML 文件输入框中给定的文件名,单独获取某个上传文件:

<?php

$file = $request->getFile('userfile');

如果是多文件上传,可根据 HTML 文件输入框中给定的文件名,获取同名上传文件的数组:

<?php

$files = $request->getFileMultiple('userfile');

备注

此处获取的文件对象本质上对应于 $_FILES。即使用户仅点击表单提交按钮而未上传任何文件,该文件依然存在。可通过 UploadedFile 中的 isValid() 方法检查文件是否确实已上传。详情请参阅 验证文件

内容协商

可通过 negotiate() 方法轻松与请求进行内容类型协商:

<?php

$language    = $request->negotiate('language', ['en-US', 'en-GB', 'fr', 'es-mx']);
$imageType   = $request->negotiate('media', ['image/png', 'image/jpg']);
$charset     = $request->negotiate('charset', ['UTF-8', 'UTF-16']);
$contentType = $request->negotiate('media', ['text/html', 'text/xml']);
$encoding    = $request->negotiate('encoding', ['gzip', 'compress']);

有关更多详情,请参阅 内容协商 页面。

类参考

备注

除了此处列出的方法外,此类还继承了 Request 类Message 类 的方法。

继承自父类的可用方法包括:

  • CodeIgniter\HTTP\Request::getIPAddress()

  • CodeIgniter\HTTP\Request::isValidIP()

  • CodeIgniter\HTTP\Request::getMethod()

  • CodeIgniter\HTTP\Request::setMethod()

  • CodeIgniter\HTTP\Request::getServer()

  • CodeIgniter\HTTP\Request::setGlobal()

  • CodeIgniter\HTTP\Request::fetchGlobal()

  • CodeIgniter\HTTP\Message::getBody()

  • CodeIgniter\HTTP\Message::setBody()

  • CodeIgniter\HTTP\Message::appendBody()

  • CodeIgniter\HTTP\Message::populateHeaders()

  • CodeIgniter\HTTP\Message::headers()

  • CodeIgniter\HTTP\Message::header()

  • CodeIgniter\HTTP\Message::hasHeader()

  • CodeIgniter\HTTP\Message::getHeaderLine()

  • CodeIgniter\HTTP\Message::setHeader()

  • CodeIgniter\HTTP\Message::removeHeader()

  • CodeIgniter\HTTP\Message::appendHeader()

  • CodeIgniter\HTTP\Message::prependHeader()

  • CodeIgniter\HTTP\Message::getProtocolVersion()

  • CodeIgniter\HTTP\Message::setProtocolVersion()

class CodeIgniter\HTTP\IncomingRequest
isCLI()
返回:

如果请求是从命令行发起的,返回 true,否则返回 false。

返回类型:

bool

isAJAX()
返回:

如果请求是 AJAX 请求,返回 true,否则返回 false。

返回类型:

bool

isSecure()
返回:

如果请求是 HTTPS 请求,返回 true,否则返回 false。

返回类型:

bool

getVar([$index = null[, $filter = null[, $flags = null]]])
参数:
  • $index (string) -- 要查找的变量名/键名。

  • $filter (int) -- 要应用的过滤器类型。过滤器列表可在 可用过滤器列表 中找到。

  • $flags (int) -- 要应用的标志。标志列表可在 过滤器标志 中找到。

返回:

如果未提供参数则返回 $_REQUEST;如果找到则返回 REQUEST 值,未找到则返回 null。

返回类型:

array|bool|float|int|object|string|null

重要

此方法仅为了向后兼容而存在。请勿在新项目中使用。即使已经在用,也建议换用其他更合适的方法。

此方法与 getGet() 完全相同,只是它获取的是 REQUEST 数据。

getGet([$index = null[, $filter = null[, $flags = null]]])
参数:
  • $index (string) -- 要查找的变量名/键名。

  • $filter (int) -- 要应用的过滤器类型。过滤器列表可在 可用过滤器列表 中找到。

  • $flags (int) -- 要应用的标志。标志列表可在 过滤器标志 中找到。

返回:

如果未提供参数则返回 $_GET;如果找到则返回 GET 值,未找到则返回 null。

返回类型:

array|bool|float|int|object|string|null

第一个参数包含要查找的 GET 项名称:

<?php

$request->getGet('some_data');

如果要获取的项目不存在,该方法将返回 null。

第二个可选参数支持通过 PHP 过滤器运行数据。将所需的过滤器类型作为第二个参数传入:

<?php

$request->getGet('some_data', FILTER_SANITIZE_FULL_SPECIAL_CHARS);

若要返回所有 GET 项的数组,请在调用时不带任何参数。

若要返回所有 GET 项并对其进行过滤,请将第一个参数设为 null,同时将第二个参数设为要使用的过滤器:

<?php

$request->getGet(null, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
// returns all GET items with string sanitation

若要返回多个 GET 参数的数组,请将所有需要的键作为数组传入:

<?php

$request->getGet(['field1', 'field2']);

此处规则相同,若要在检索参数时进行过滤,请将第二个参数设为要应用的过滤器类型:

<?php

$request->getGet(['field1', 'field2'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
getPost([$index = null[, $filter = null[, $flags = null]]])
参数:
  • $index (string) -- 要查找的变量名/键名。

  • $filter (int) -- 要应用的过滤器类型。过滤器列表可在 此处 找到。

  • $flags (int) -- 要应用的标志。标志列表可在 此处 找到。

返回:

如果未提供参数则返回 $_POST;如果找到则返回 POST 值,未找到则返回 null。

返回类型:

array|bool|float|int|object|string|null

此方法与 getGet() 完全相同,只是它获取的是 POST 数据。

getPostGet([$index = null[, $filter = null[, $flags = null]]])
参数:
  • $index (string) -- 要查找的变量名/键名。

  • $filter (int) -- 要应用的过滤器类型。过滤器列表可在 可用过滤器列表 中找到。

  • $flags (int) -- 要应用的标志。标志列表可在 过滤器标志 中找到。

返回:

如果未指定参数,则返回合并后的 $_POST$_GET (名称冲突时优先使用 POST 值);否则先查找 POST 值,未找到则查找 GET 值,若均未找到则返回 null。

返回类型:

array|bool|float|int|object|string|null

此方法的工作方式与 getPost()getGet() 基本相同,只是将二者结合。它会同时在 POST 和 GET 流中搜索数据,先查找 POST,然后查找 GET:

<?php

$request->getPostGet('field1');

如果未指定索引,将返回合并后的 POST 和 GET 流。若发生名称冲突,将优先使用 POST 数据。

getGetPost([$index = null[, $filter = null[, $flags = null]]])
参数:
  • $index (string) -- 要查找的变量名/键名。

  • $filter (int) -- 要应用的过滤器类型。过滤器列表可在 可用过滤器列表 中找到。

  • $flags (int) -- 要应用的标志。标志列表可在 过滤器标志 中找到。

返回:

如果未指定参数,则返回合并后的 $_GET$_POST (名称冲突时优先使用 GET 值);否则先查找 GET 值,未找到则查找 POST 值,若均未找到则返回 null。

返回类型:

array|bool|float|int|object|string|null

此方法的工作方式与 getPost()getGet() 基本相同,只是将二者结合。它会同时在 GET 和 POST 流中搜索数据,先查找 GET,然后查找 POST:

<?php

$request->getGetPost('field1');

如果未指定索引,将返回合并后的 GET 和 POST 流。若发生名称冲突,将优先使用 GET 数据。

getCookie([$index = null[, $filter = null[, $flags = null]]])
参数:
  • $index (array|string|null) -- COOKIE 名称

  • $filter (int) -- 要应用的过滤器类型。过滤器列表可在 可用过滤器列表 中找到。

  • $flags (int) -- 要应用的标志。标志列表可在 过滤器标志 中找到。

返回:

如果未提供参数则返回 $_COOKIE;如果找到则返回 COOKIE 值,未找到则返回 null。

返回类型:

array|bool|float|int|object|string|null

此方法与 getPost()getGet() 完全相同,只是它获取的是 Cookie 数据:

<?php

$request->getCookie('some_cookie');
$request->getCookie('some_cookie', FILTER_SANITIZE_FULL_SPECIAL_CHARS); // with filter

若要返回多个 Cookie 值的数组,请将所有需要的键作为数组传入:

<?php

$request->getCookie(['some_cookie', 'some_cookie2']);

备注

Cookie 辅助函数 中的 get_cookie() 函数不同,此方法不会自动附加配置的 Config\Cookie::$prefix 值。

getServer([$index = null[, $filter = null[, $flags = null]]])
参数:
  • $index (array|string|null) -- 值名称

  • $filter (int) -- 要应用的过滤器类型。过滤器列表可在 可用过滤器列表 中找到。

  • $flags (int) -- 要应用的标志。标志列表可在 过滤器标志 中找到。

返回:

如果找到则返回 $_SERVER 项的值,未找到则返回 null。

返回类型:

array|bool|float|int|object|string|null

此方法与 getPost()getGet()getCookie() 方法完全相同,只是它获取的是 Server 数据($_SERVER):

<?php

$request->getServer('some_data');

若要返回多个 $_SERVER 值的数组,请将所有需要的键作为数组传入。

<?php

$request->getServer(['SERVER_PROTOCOL', 'REQUEST_URI']);
getUserAgent()
返回:

SERVER 数据中的 User Agent 字符串;如果未找到则返回 null。

返回类型:

CodeIgniter\HTTP\UserAgent

此方法从 SERVER 数据中返回 User Agent 实例:

<?php

$request->getUserAgent();
getPath()
返回:

当前相对于 baseURL 的 URI 路径

返回类型:

string

此方法返回当前相对于 baseURL 的 URI 路径。

备注

v4.4.0 之前,这是确定“当前 URI”最安全的方法,因为 IncomingRequest::$uri 可能无法识别应用程序中完整的基准 URL 配置。