请求组件¶
概览¶
Phalcon\Http\Request是一个封装实际 HTTP 请求(通常由浏览器发起)并发送到我们应用程序的组件。该对象是一个简单的值对象,它在调度器和控制器类之间传递,封装了 HTTP 请求环境。它还提供了对诸如标头数据、文件、方法、变量等信息的轻松访问。Phalcon\Http\RequestPHP 自动填充超全局数组
<?php
use Phalcon\Http\Request;
$request = new Request();
// POST
if (true === $request->isPost()) {
    // AJAX
    if (true === $request->isAjax()) {
        // ....
    }
}
获取值¶
PHP automatically fills the superglobal arrays $_GET, $_POST和$_REQUEST根据请求类型而定。这些数组包含表单提交或通过 URL 发送的参数中的值。数组中的变量从未被清理,并可能包含非法字符甚至恶意代码,这可能导致SQL 注入或跨站脚本攻击 (XSS)攻击。
Phalcon\Http\Request允许你访问存储在$_GET, $_POST和$_REQUEST数组中的值,并使用过滤器服务对其清理或过滤。
有五种方法允许你从请求中检索提交的数据: -get() - getQuery() - getPost() - getPut() - getServer()
所有(除了getServer()之外)接受以下参数:
| 名称 | 描述 | 
|---|---|
name |  要获取的值的名称 | 
filters |  (数组/字符串)要应用到该值的清理器 | 
defaultValue |  如果元素未定义则返回 (null) |  
notAllowEmpty |  如果设置(默认)且值为空,则返回defaultValue; 否则null |  
noRecursive |  在值上递归应用清理器(如果值是数组) | 
<?php
use Phalcon\Http\Request;
$request = new Request();
$request->get(
    $name = null,            // string
    $filters = null,         // mixed
    $defaultValue = null,    // mixed
    $notAllowEmpty = false,  // bool
    $noRecursive = false     // bool
): mixed
getServer()仅接受一个name(字符串)变量,表示需要检索的服务器变量的名称。
$_REQUEST¶
The $_REQUEST超全局数组包含一个关联数组,其中包含$_GET, $_POST和$_COOKIE的内容。你可以通过调用get()方法,在Phalcon\Http\Request对象中如下获取数组中存储的数据:
示例
获取userEmail字段来自$_REQUEST超全局:
获取userEmail字段来自$_REQUEST超全局。使用email清理器清理该值:
<?php
use Phalcon\Http\Request;
$request = new Request();
$email = $request->get('userEmail', 'email', 'some@example.com');
获取userEmail字段来自$_REQUEST超全局。不清理它。如果参数为 null,则返回默认值:
<?php
use Phalcon\Http\Request;
$request = new Request();
$email = $request->get('userEmail', null, 'some@example.com');
$_GET¶
The $_GET超全局数组包含一个关联数组,其中包含通过 URL 参数(也称为查询字符串)传递给当前脚本的变量。你可以通过调用getQuery()方法如下获取数组中存储的数据:
示例
获取userEmail字段来自$_GET超全局:
获取userEmail字段来自$_GET超全局。使用email清理器清理该值:
<?php
use Phalcon\Http\Request;
$request = new Request();
$email = $request->getQuery('userEmail', 'email', 'some@example.com');
获取userEmail字段来自$_GET超全局。不清理它。如果参数为 null,则返回默认值:
<?php
use Phalcon\Http\Request;
$request = new Request();
$email = $request->getQuery('userEmail', null, 'some@example.com');
$_POST¶
The $_POST超全局数组包含一个关联数组,其中包含在使用application/x-www-form-urlencoded或multipart/form-data作为 HTTPContent-Type的请求中通过 HTTP POST 方法传递给当前脚本的变量。你可以通过调用getPost()方法如下获取数组中存储的数据:
示例
获取userEmail字段来自$_POST超全局:
获取userEmail字段来自$_POST超全局。使用email清理器清理该值:
<?php
use Phalcon\Http\Request;
$request = new Request();
$email = $request->getPost('userEmail', 'email', 'some@example.com');
获取userEmail字段来自$_POST超全局。不清理它。如果参数为 null,则返回默认值:
<?php
use Phalcon\Http\Request;
$request = new Request();
$email = $request->getPost('userEmail', null, 'some@example.com');
放置¶
请求对象解析内部接收到的 PUT 流。你可以通过调用getPut()方法如下获取数组中存储的数据:
示例
获取userEmail字段来自PUT流:
获取userEmail字段来自PUT流。使用email清理器清理该值:
<?php
use Phalcon\Http\Request;
$request = new Request();
$email = $request->getPut('userEmail', 'email', 'some@example.com');
获取userEmail字段来自PUT流。不清理它。如果参数为 null,则返回默认值:
<?php
use Phalcon\Http\Request;
$request = new Request();
$email = $request->getPut('userEmail', null, 'some@example.com');
$_SERVER¶
The $_SERVER超全局数组包含一个数组,其中包含诸如标头、路径和脚本位置之类的信息。你可以通过调用getServer()方法如下获取数组中存储的数据:
示例
获取SERVER_NAME值来自$_SERVER超全局:
<?php
use Phalcon\Http\Request;
$request = new Request();
$name = $request->getServer('SERVER_NAME');
预设清理器¶
在你的应用程序中,某些字段通常会使用相同的名称。从你的应用程序中的表单发布的字段可以与不同区域中的另一个表单具有相同的名称和功能。这种行为的例子可能是id字段,name等等。
为了简化清理过程,在检索此类字段时,Phalcon\Http\Request提供了一种方法,根据 HTTP 方法在创建对象时定义这些清理过滤器。
<?php
use Phalcon\Di\Di;
use Phalcon\Filter;
use Phalcon\Http\Request;
$container = new Di();
$container->set(
    'request',
    function () {
        $request = new Request();
        $request
            ->setParameterFilters(
                'id', 
                Filter::FILTER_ABSINT, 
                [
                    'post'
                ]
            )
            ->setParameterFilters(
                'name', 
                [
                    'trim', 
                    'string'
                ], 
                [
                    'post'
                ]
            )
        ;
        return $request;
    }
);
上述代码将自动清理任何从具有名称id或name的表单 POST 的参数,并使用它们各自的过滤器。清理发生在调用以下方法时(每个 HTTP 方法一个) -getFilteredPost() - getFilteredPut() - getFilteredQuery()
这些方法接受与getPost(), getPut()和getQuery()相同的参数,但没有$filter参数。
控制器¶
如果您使用Phalcon\Di\FactoryDefault容器,Phalcon\Http\Request已经为你注册好了。访问请求环境最常见的地方是在控制器的操作中。要从控制器访问Phalcon\Http\Request对象,你需要使用控制器的$this->request公共属性:
<?php
use Phalcon\Http\Request;
use Phalcon\Mvc\Controller;
/**
 * Class PostsController
 * 
 * @property Request $request
 */
class PostsController extends Controller
{
    public function saveAction()
    {
        // Check if the request has been made with POST
        if (true === $this->request->isPost()) {
            // Access POST data
            $customerName = $this
                ->request
                ->getPost('name');
            $customerBorn = $this
                ->request
                ->getPost('born', 'string', '1984');
        }
    }
}
检查操作¶
The Phalcon\Http\Request组件包含许多帮助你检查当前操作的方法。例如,如果你想检查某个特定请求是否是通过 AJAX 发起的,可以使用isAjax()方法。所有方法都以前缀is.
| 名称 | 描述 | 
|---|---|
isAjax() |  检查请求是否使用 AJAX 发起 | 
isConnect() |  检查 HTTP 方法是否为 CONNECT | 
isDelete() |  检查 HTTP 方法是否为 DELETE | 
isGet() |  检查 HTTP 方法是否为 GET | 
isHead() |  检查 HTTP 方法是否为 HEAD | 
isMethod() |  检查HTTP方法是否与传递的方法之一匹配 | 
isOptions() |  检查HTTP方法是否为OPTIONS | 
isPatch() |  检查HTTP方法是否为PATCH | 
isPost() |  检查HTTP方法是否为POST | 
isPurge() |  检查HTTP方法是否为PURGE(Squid和Varnish支持) | 
isPut() |  检查HTTP方法是否为PUT | 
isSecure() |  检查请求是否通过任何安全层发出 | 
isSoap() |  检查请求是否通过SOAP发出 | 
isTrace() |  检查HTTP方法是否为TRACE | 
isValidHttpMethod() |  检查某个方法是否为有效的HTTP方法 | 
检查存在性¶
有几种方法可用于检查请求中元素的存在。这些方法以前缀开头has根据使用的方法,您可以检查元素是否存在于$_REQUEST, $_GET, $_POST, $_SERVER, $_FILES,PUT缓存和请求头中。
| 名称 | 描述 | 
|---|---|
has() |  检查$_REQUEST超全局变量是否包含某个元素 | 
hasFiles() |  检查请求是否有任何上传文件 | 
hasHeader() |  检查头部是否有某个元素 | 
hasPost() |  检查$_POST超全局变量是否包含某个元素 | 
hasPut() |  检查PUT数据是否包含某个元素 | 
hasQuery() |  检查$_GET超全局变量是否包含某个元素 | 
hasServer() |  检查$_SERVER超全局变量是否包含某个元素 | 
numFiles() |  返回请求中存在的文件数量 | 
请求信息¶
The Phalcon\Http\Request对象提供了一些方法,用于提供有关请求的其他信息。
身份验证¶
| 名称 | 描述 | 
|---|---|
getBasicAuth() |  获取浏览器/客户端接受的身份验证信息 | 
getDigestAuth() |  获取浏览器/客户端接受的身份验证信息 | 
客户端¶
| 名称 | 描述 | 
|---|---|
getClientAddress() |  获取客户端可能的IPv4地址 | 
getClientCharsets() |  获取浏览器/客户端接受的字符集数组及其质量 | 
getUserAgent() |  获取用于发出请求的HTTP用户代理 | 
getHTTPReferer() |  获取引用当前请求的网页 | 
内容¶
| 名称 | 描述 | 
|---|---|
getAcceptableContent() |  获取浏览器/客户端接受的mime/types数组及其质量 | 
getBestAccept() |  获取浏览器/客户端接受的最佳mime/type | 
getContentType() |  获取请求的内容类型 | 
getJsonRawBody() |  获取解码后的JSON HTTP原始请求体 | 
getRawBody() |  获取HTTP原始请求体 | 
i18n¶
| 名称 | 描述 | 
|---|---|
getBestCharset() |  获取浏览器/客户端接受的最佳字符集 | 
getBestLanguage() |  获取浏览器/客户端接受的最佳语言 | 
getLanguages() |  获取浏览器/客户端接受的语言数组及其质量 | 
服务器¶
| 名称 | 描述 | 
|---|---|
getPort() |  获取请求所用端口的信息 | 
getServerAddress() |  获取活动服务器地址IP | 
getServerName() |  获取活动服务器名称 | 
getScheme() |  获取HTTP模式(http/https) | 
getURI() |  获取已发出请求的HTTP URI。如果true作为参数传递,则不会返回查询部分 |  
<?php
use Phalcon\Http\Request;
$request = new Request();
if ($request->isAjax()) {
    echo 'The request was made with Ajax';
}
// Check the request layer
if ($request->isSecure()) {
    echo 'The request was made using a secure layer';
}
一些方法:
获取服务器的IP地址。例如。192.168.0.100 获取客户端的IP地址例如。201.245.53.51 获取用户代理(HTTP_USER_AGENT) 获取浏览器接受的最佳内容。例如text/xml 获取浏览器接受的最佳字符集。例如。utf-8 获取浏览器配置中接受的最佳语言。例如。en-us 方法¶
getMethod()返回请求所用的HTTP方法。如果X-HTTP-Method-Override头部已设置,并且方法是POST,则它用于确定“真实”的HTTP方法。该_method请求参数还可以用于确定HTTP方法,setHttpMethodParameterOverride(true)已被调用。该方法始终返回大写字符串。
<?php
use Phalcon\Http\Request;
$request = new Request();
// POST
$_SERVER['REQUEST_METHOD'] = 'POST';
echo $request->getMethod();
/**
 * header('X-HTTP-Method-Override: GET');
 */ 
$_SERVER['REQUEST_METHOD'] = 'POST';
$request->setHttpMethodParameterOverride(true);
echo $request->getMethod();
// GET
$_SERVER['REQUEST_METHOD'] = 'POST';
$_REQUEST['_method']       = 'GET';
$request->setHttpMethodParameterOverride(true);
echo $request->getMethod();
依赖注入¶
The Phalcon\Http\Request对象实现了Phalcon\Di\InjectionAwareInterface接口。因此,DI容器是可用的,并可以通过getDI()方法检索。也可以通过setDI()方法设置容器。
使用头部工作¶
请求头部包含有用信息,允许您采取必要的步骤向用户发送适当的响应。该Phalcon\Http\Request暴露了getHeader()和getHeaders()方法。
<?php
use Phalcon\Http\Request;
$request = new Request;
$_SERVER["HTTP_HOST"] = "example.com";
$request->getHttpHost(); // example.com
$_SERVER["HTTP_HOST"] = "example.com:8080";
$request->getHttpHost(); // example.com:8080
$request->setStrictHostCheck(true);
$_SERVER["HTTP_HOST"] = "ex=am~ple.com";
$request->getHttpHost(); // UnexpectedValueException
$_SERVER["HTTP_HOST"] = "ExAmPlE.com";
$request->getHttpHost(); // example.com
The getHttpHost()方法将返回请求所用的主机名。该方法将尝试按以下顺序查找主机名: -$_SERVER["HTTP_HOST"] - $_SERVER["SERVER_NAME"] - $_SERVER["SERVER_ADDR"]
可选地getHttpHost()验证并对主机名进行严格检查。为此,您可以使用setStrictHostCheck()方法设置容器。
上传文件¶
另一个常见任务是文件上传。Phalcon\Http\Request提供了一种面向对象的方式来处理文件。为了使整个上传过程正常工作,您需要对您的php.ini(参见php-uploads)。
<?php
use Phalcon\Http\Request;
use Phalcon\Mvc\Controller;
/**
 * Class PostsController
 * 
 * @property Request $request
 */
class PostsController extends Controller
{
    public function uploadAction()
    {
        // if ($this->request->numFiles() > 0) {
        if ($this->request->hasFiles()) {
            $files = $this->request->getUploadedFiles();
            foreach ($files as $file) {
                echo $file->getName(), ' ', $file->getSize(), '\n';
                $file->moveTo(
                    'files/' . $file->getName()
                );
            }
        }
    }
}
每个由Phalcon\Http\Request::getUploadedFiles()返回的对象都是Phalcon\Http\Request\File的实例,它实现了Phalcon\Http\Request\FileInterface类。使用$_FILES超全局数组提供相同的行为。Phalcon\Http\Request\File仅封装与每个随请求上传的文件相关的信息。
The getUploadedFiles()接受两个参数。
| 名称 | 描述 | 
|---|---|
$onlySuccessful |  仅包含成功的上传 | 
$namedKeys |  返回由上传过程获得的命名键数组 | 
该方法返回一个Phalcon\Http\Request\File对象数组。每个对象提供以下属性和方法,允许您处理上传的文件:
| 名称 | 描述 | 
|---|---|
getError(): string |  返回此文件发生的任何错误 | 
getExtension(): string |  返回文件的扩展名 | 
getKey(): string |  返回文件的内部键 | 
getName(): string |  返回上传文件的真实名称 | 
getRealType(): string |  使用finfo返回上传文件的真实mime类型 | 
getSize(): int |  返回上传文件的文件大小 | 
getTempName(): string |  返回上传文件的临时名称 | 
getType(): string |  返回浏览器报告的mime类型。此mime类型不是完全安全的,使用getRealType()代替 |  
isUploadedFile(): bool |  检查文件是否通过POST. |  
moveTo(string $destination): bool |  将临时文件移动到应用程序内的目标位置 | 
事件¶
The Phalcon\Http\Request对象实现了Phalcon\Events\EventsAware接口。因此,getEventsManager()和setEventsManager()可供您使用。
| 事件 | 描述 | 可以停止操作 | 
|---|---|---|
afterAuthorizationResolve |  在授权已解决时触发 | 否 | 
beforeAuthorizationResolve |  在授权已解决之前触发 | 是 | 
在使用HTTP授权时,Authorization头具有以下格式:
其中<type>是一种身份验证类型。常见的类型是Basic。其他身份验证类型在IANA注册身份验证方案中描述和AWS服务器的身份验证(AWS4-HMAC-SHA256)。在大多数使用情况下,身份验证类型为: *AWS4-HMAC-SHA256 * Basic * Bearer * Digest * HOBA * Mutual * Negotiate * OAuth * SCRAM-SHA-1 * SCRAM-SHA-256 * vapid
您可以使用request:beforeAuthorizationResolve和request:afterAuthorizationResolve事件在授权解析前后执行附加操作。
The request:beforeAuthorizationResolve接收SERVER带有键的数组server作为事件的第二个参数。
The request:afterAuthorizationResolve接收SERVER带有键的数组server以及带有键的头部headers.
需要一个自定义授权解析器。
不使用自定义授权解析器的示例:
<?php
use Phalcon\Http\Request;
$_SERVER['HTTP_AUTHORIZATION'] = 'Enigma Secret';
$request = new Request();
print_r($request->getHeaders());
结果:
使用自定义授权解析器的示例:
<?php
use Phalcon\Di\Di;
use Phalcon\Events\Event;
use Phalcon\Http\Request;
use Phalcon\Events\Manager;
class NegotiateAuthorizationListener
{
    public function afterAuthorizationResolve(Event $event, Request $request, array $data)
    {
        if (empty($data['server']['CUSTOM_KERBEROS_AUTH'])) {
            return false;
        }
        list($type,) = explode(
            ' ', 
            $data['server']['CUSTOM_KERBEROS_AUTH'], 
            2
        );
        if (!$type || stripos($type, 'negotiate') !== 0) {
            return false;
        }
        return [
           'Authorization'=> $data['server']['CUSTOM_KERBEROS_AUTH'],
        ];
    }
}
$_SERVER['CUSTOM_KERBEROS_AUTH'] = 'Negotiate '
                                 . 'a87421000492aa874209af8bc028';
$di = new Di();
$di->set(
    'eventsManager',
    function () {
        $manager = new Manager();
        $manager->attach(
            'request',
            new NegotiateAuthorizationListener()
        );
        return $manager;
    }
);
$request = new Request();
$request->setDI($di);
print_r(
    $request->getHeaders()
);
结果: