Phalcon框架中的request和response常用方法

admin 发表于 [PHP] 分类,标签: PHP开发框架 知识总结 Phalcon
0

Phalcon 框架 Cookie

Phalcon\Http\Response\Cookies(不是Phalcon\Http\Cookie)是一个为响应设置cookie的容器,类似于PHP中的setcookie()函数。

这个容器中设置的每个cookie都是一个Phalcon\Http\Cookie类实例,容器的send()方法实际是添加响应头Set-Cookie指令。

在Phalcon中,最终会调用:

Phalcon\Http\Response->sendHeaders()
Phalcon\Http\Response->sendCookies()

这里的Phalcon\Http\Response->sendCookies()内部实际调用Phalcon\Http\Response\Cookies的send()方法。

如下例子:

//在控制器方法中添加如下代码:
$this->cookies->useEncryption(false);
$this->cookies->set("test-cookie","ffffffffffffffff");
 
$this->cookies->send();
return;
 
//响应头
Connection  Keep-Alive
Content-Length  10
Content-Type    text/html
Date        Mon, 08 Sep 2014 04:20:17 GMT
Keep-Alive  timeout=5, max=100
Server      Apache/2.2.27 (Unix) PHP/5.5.15
Set-Cookie  test-cookie=ffffffffffffffff; path=/; httponly test-cookie=ffffffffffffffff; path=/; httponly

代码中设置了一个cookie,然后调用容器的send()方法,在客户端查看响应头,发现Set-Cookie指令中test-cookie设置了两 次,这个说明Phalcon在响应时也调用了一次send()方法,这个就可以证明Phalcon在响应时调用的sendCookies()方法内部就是 调用cookie容器的send()方法。

 

Phalcon\Http\Response有三个和cookie有关的方法:

 

Phalcon\Http\Response::getCookies();
Phalcon\Http\Response::setCookies($cookies);
Phalcon\Http\Response::sendCookies();

 

分别获取和设置Response的Cookies容器(\Phalcon\Http\Response\CookiesInterface 实例),sendCookies()是调用容器的send()方法发送cookie。

还有一个问题是,如何获取来自请求的cookie?你可以发现,在Phalcon\Http\Request中并不存在类似getCookies()方法,难道要使用$_COOKIE全局数组?Phalcon文档对于这个并没有提及。使用如下例子:

//使用的请求头信息
Accept      text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Cache-Control   max-age=0
Connection  keep-alive
Cookie      test-cookie=only+for+test+cookie.
Host        192.168.1.168
User-Agent  Mozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
 
//控制器代码
$this->cookies->set("hello-cookie","hello cccccc kie.");
if($this->cookies->has("test-cookie")){
    echo $this->cookies->get("test-cookie")->getValue();
}     
print_r($this->cookies);
$this->view->disable();
 
//输出
only for test cookie.
 
Phalcon\Http\Response\Cookies Object
(
    [_dependencyInjector:protected] => Phalcon\DI\FactoryDefault Object
    [_registered:protected] => 
    [_useEncryption:protected] => 
    [_cookies:protected] => Array
    (
        [hello-cookie] => Phalcon\Http\Cookie Object
        (
            [_readed:protected] => 1
            [_restored:protected] => 
            [_useEncryption:protected] => 
            [_dependencyInjector:protected] => Phalcon\DI\FactoryDefault Object
            [_filter:protected] => 
            [_name:protected] => hello-cookie
            [_value:protected] => hello cccccc kie.
            [_expire:protected] => 0
            [_path:protected] => /
            [_domain:protected] => 
            [_secure:protected] => 
            [_httpOnly:protected] => 1
        )
    )
)

请求中发送了cookie(test-cookie=only+for+test+cookie.)

$this->cookies->get("test-cookie")获取到了这个来自请求的cookie,但是从 Phalcon\Http\Response\Cookies输出来看,这个cookie并不在它的_cookies数组中,观察到代码中设置了一个叫 hello-cookie的cookie,而它在_cookies数组中,所以应该是只有设置了才进入_cookies数 组,$this->cookies->get("test-cookie")先判断在不在_cookies数组中,否则再判断是不是来自请求 的cookie。

注意,$this->cookies->get("test-cookie")返回的是一个来自请求的Phalcon\Http\Cookie的类实例,所以可以调用相关方法。

Phalcon对管理来自请求的cookie比较隐晦,它只能通过Phalcon\Http\Response\Cookies容器相关方法调用,从名字来看,不应该是它的一部分。

 

HTTP 请求环境(Request Environment)

每个HTTP请求(通常来源于浏览器)会包含请求的附加信息,比如头部数据,文件,变量等。一个基于Web的应用需要解析这些信息以提供正确的响应返回到请求者。Phalcon\Http\Request封装了这些请求的信息,允许你以一个面向对象的方式访问它。

<?php
// Getting a request instance
$request = new \Phalcon\Http\Request();
 
// Check whether the request was made with method POST
if ($request->isPost() == true) {
 
    // Check whether the request was made with Ajax
    if ($request->isAjax() == true) {
        echo "Request was made using POST and AJAX";
    }
}

 

获取值(Getting Values)

PHP更加请求的类型自动地填充$_GET和$_POST超全局数组。这些数组保存了来自提交表单的值或者通过URL传递的参数值。在这些数组中的变量没有被清理兵器包含非法字符,甚至是可能导致SQL注入或跨站脚本(XSS)攻击的恶意代码。

Phalcon\Http\Request allows you to access the values stored in the $_REQUEST, $_GET and $_POST arrays and sanitize or filter them with the ‘filter’ service, (by default Phalcon\Filter). The following examples offer the same behavior:

Phalcon\Http\Request允许你访问这些存储在$_REQUEST, $_GET 和 $_POST数组中的值并且通过使用'filter'服务清理或过滤它们,(默认是Phalcon\Filter)。

以下例子提供了相同的行为:

<?php
// Manually applying the filter
$filter = new Phalcon\Filter();
 
$email  = $filter->sanitize($_POST["user_email"], "email");
 
// Manually applying the filter to the value
$filter = new Phalcon\Filter();
$email  = $filter->sanitize($request->getPost("user_email"), "email");
 
// Automatically applying the filter
$email = $request->getPost("user_email", "email");
 
// Setting a default value if the param is null
$email = $request->getPost("user_email", "email", "some@example.com");
 
// Setting a default value if the param is null without filtering
$email = $request->getPost("user_email", null, "some@example.com");

(这写个用法基本要牢记了,要么直接使用filter清理,要么间接使用)

 

控制器中访问请求(Accessing the Request from Controllers)

最通用的方法请求环境的地方是在控制器的动作中。为了从访问控制器访问Phalcon\Http\Request对象你将需要使用$this->request控制器的公共属性:(注意,DI资源通过魔术方法映射到公共属性,并非真的是它的公共属性)

<?php
use Phalcon\Mvc\Controller;
class PostsController extends Controller {
    public function indexAction() {
    }
 
    public function saveAction() {
        // Check if request has made with POST
        if ($this->request->isPost() == true) {
            // Access POST data
            $customerName = $this->request->getPost("name");
            $customerBorn = $this->request->getPost("born");
        }
    }
}

 

文件上传(Uploading Files)

另一个常见的任务是文件上传。

Phalcon\Http\Request提供了一个面向对象的方法去完成这个任务:

<?php
use Phalcon\Mvc\Controller;
class PostsController extends Controller {
    public function uploadAction() {
        // Check if the user has uploaded files
        if ($this->request->hasFiles() == true) {
            // Print the real file names and sizes
            foreach ($this->request->getUploadedFiles() as $file) {
                //Print file details
                echo $file->getName(), " ", $file->getSize(), "\n";
                //Move the file into the application
                $file->moveTo('files/' . $file->getName());
            }
        }
    }
}

通过Phalcon\Http\Request::getUploadedFiles()返回的每个对象是一个Phalcon\Http\Request\File类的实例。

使用$_FILES超全局数组提供类似行为。Phalcon\Http\Request\File仅封装了请求的跟每个上传文件相关的信息。

 

使用头信息(Working with Headers)

跟上面提到的一样,请求头包含了允许我们去发送合适的响应到用户的有用的信息。以下例子展示这些信息的用法:

<?php
// get the Http-X-Requested-With header
$requestedWith = $response->getHeader("HTTP_X_REQUESTED_WITH");
if ($requestedWith == "XMLHttpRequest") {
    echo "The request was made with Ajax";
}
 
// Same as above
if ($request->isAjax()) {
    echo "The request was made with Ajax";
}
 
// Check the request layer
if ($request->isSecureRequest() == true) {
    echo "The request was made using a secure layer";
}
 
// Get the servers's ip address. ie. 192.168.0.100
$ipAddress = $request->getServerAddress();
 
// Get the client's ip address ie. 201.245.53.51
$ipAddress = $request->getClientAddress();
 
// Get the User Agent (HTTP_USER_AGENT)
$userAgent = $request->getUserAgent();
 
// Get the best acceptable content by the browser. ie text/xml
$contentType = $request->getAcceptableContent();
 
// Get the best charset accepted by the browser. ie. utf-8
$charset = $request->getBestCharset();
 
// Get the best language accepted configured in the browser. ie. en-us
$language = $request->getBestLanguage();

 

返回响应(Returning Responses)

返回响应到客户端是HTTP周期的一部分。Phalcon\Http\Response是一个设计来完成这个任务的Phalcon组件。HTTP响应通常由头部和主体组成。

以下是基本用法的例子:

<?php
//Getting a response instance
$response = new \Phalcon\Http\Response();
 
//Set status code
$response->setStatusCode(404, "Not Found");
 
//Set the content of the response
$response->setContent("Sorry, the page doesn't exist");
 
//Send response to the client
$response->send();

如果你使用全栈MVC就不需要受到穿件响应。不过,如果你要从控制器的动作中直接返回一个响应,以下是一个示例:

<?php
class FeedController extends Phalcon\Mvc\Controller {
    public function getAction() {
        // Getting a response instance
        $response = new \Phalcon\Http\Response();
 
        $feed = //.. load here the feed
 
        //Set the content of the response
        $response->setContent($feed->asString());
 
        //Return the response
        return $response;
    }
}

 

使用头部信息(Working with Headers)

头部是HTTP响应的重要部分。它包含了关于响应状态的有用的信息,比如HTTP状态,响应类型等。

你可以像下面的代码进行HTTP请求头的设置:

<?php
//Setting a header by it's name
$response->setHeader("Content-Type", "application/pdf");
$response->setHeader("Content-Disposition", 'attachment; filename="downloaded.pdf"');
 
//Setting a raw header
$response->setRawHeader("HTTP/1.1 200 OK");

在内部由 Phalcon\Http\Response\Headers 管理头部。在发送到客户端之前由这个类获取头部:

<?php
//Get the headers bag
$headers = $response->getHeaders();
 
//Get a header by its name
$contentType = $response->getHeaders()->get("Content-Type");

 

重定向(Making Redirections)

Phalcon\Http\Response 您还可以执行HTTP重定向

<?php
//Redirect to the default URI
$response->redirect();
 
//Redirect to the local base URI
$response->redirect("posts/index");
 
//Redirect to an external URL
$response->redirect("http://en.wikipedia.org", true);
 
//Redirect specifyng the HTTP status code
$response->redirect("http://www.qixing318.com/blog/", true, 301);

所有内部URI的产生都是使用'url'服务(默认Phalcon\Mvc\Url)。

<?php
//Redirect based on a named route
return $response->redirect([
    'for' => 'index-lang',
    'lang' => 'jp',
    'controller' => 'index'
]);

注意重定向不会禁用视图组件,所以如果有视图关联到当前动作,它总会被执行。

你可以通过在控制器中执行$this->view->disable()来禁用视图。

 

HTTP 缓存(HTTP Cache)

当一个页面的第一次请求时,应用发送如下头信息值可以修改HTTP缓存。

Expires: With this header the application can set a date in the future or the past telling the browser when the page must expire. 

Cache-Control: This header allows to specify how much time a page should be considered fresh in the browser. 

Last-Modified: This header tells the browser which was the last time the site was updated avoiding page re-loads

ETag: An etag is a unique identifier that must be created including the modification timestamp of the current page

 

设置过期时间(Setting an Expiration Time)

设置一个页面在客户端(浏览器)缓存的最容易和最高效的方法设置过期日期。

<?php
$expireDate = new DateTime();
$expireDate->modify('+2 months');
 
$response->setExpires($expireDate);

设置一个过去的日期表示不缓存:

<?php
$expireDate = new DateTime();
$expireDate->modify('-10 minutes');
 
$response->setExpires($expireDate);

浏览器依赖客户端的时钟去访问日期是否过期….

 

Cache-Control标签

安全的方法是设置缓存的秒数(因为设置过期日期依赖客户端时钟):

<?php
//Starting from now, cache the page for one day
$response->setHeader('Cache-Control', 'max-age=86400');

相反的效果(避免缓存):

<?php
//Never cache the served page
$response->setHeader('Cache-Control', 'private, max-age=0, must-revalidate');

 

E-Tag标签

唯一验证器,帮助浏览器认识页面在两次请求中是否被改变:

<?php
//Calculate the E-Tag based on the modification time of the latest news
$recentDate = News::maximum(array('column' => 'created_at'));
$eTag = md5($recentDate);
 
//Send an E-Tag header
$response->setHeader('E-Tag', $eTag);

 

Phalcon框架 Cookie 管理(Cookies Management)

Cookies是一个非常有用的在客户端存储小块数据的方法。Phalcon\Http\Response\Cookies为cookies扮演一个全局袋子。

在请求执行过程中Cookies被存储到这个袋子中并在请求结束时自动地发送。

 

基本用法(Basic Usage)

<?php
class SessionController extends Phalcon\Mvc\Controller {
    public function loginAction() {
        //Check if the cookie has previously set
        if ($this->cookies->has('remember-me')) {
            //Get the cookie
            $rememberMe = $this->cookies->get('remember-me');
            //Get the cookie's value
            $value = $rememberMe->getValue();
        }
    }
 
    public function startAction() {
        $this->cookies->set('remember-me', 'some value', time() + 15 * 86400);
    }
}

 

Cookie 的加密和解密(Encryption/Decryption of Cookies)

默认,cookies在发送到客户端前被自动地加密,在获取时解密。这个阻止了未认证用户看到cookies内容。不过敏感数据集不应该存储在cookies中。

禁用加密方法:

<?php
$di->set('cookies', function() {
    $cookies = new Phalcon\Http\Response\Cookies();
    $cookies->useEncryption(false);
    return $cookies;
});

要启用加密服务,全局服务crypt需要设置一个key:

<?php
$di->set('crypt', function() {
    $crypt = new Phalcon\Crypt();
    $crypt->setKey('#1dj8$=dp?.ak//j1V$'); //Use your own key!
    return $crypt;
});

向客户发送没有经过加密,包括复杂对象结构、结果集、服务信息等的cookie数据时,可能使内部应用程序的逻辑有可能被攻击者利用攻击。

如果你不想使用加密,我们强烈建议你只发送非常基本的cookie数据如数字或字符串,发送不加密cookies数据到客户端将暴露一些信息之类….

文章译自Phalcon官方文档,详情还请参见官方

发表我的评论