1. 程式人生 > >YII Framework學習教程-YII的request\response-2011-11-21

YII Framework學習教程-YII的request\response-2011-11-21

    YII中提供了CHttpRequest,封裝了請求常用的方法。具體程式碼如下:

class CHttpRequest extends CApplicationComponent
{
	public $enableCookieValidation=false;
	public $enableCsrfValidation=false;
	public $csrfTokenName='YII_CSRF_TOKEN';
	public $csrfCookie;
	private $_requestUri;
	private $_pathInfo;
	private $_scriptFile;
	private $_scriptUrl;
	private $_hostInfo;
	private $_baseUrl;
	private $_cookies;
	private $_preferredLanguage;
	private $_csrfToken;
	private $_deleteParams;
	private $_putParams;
	public function init()
	{
		parent::init();
		$this->normalizeRequest();
	}
	protected function normalizeRequest()
	{
		// normalize request
		if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
		{
			if(isset($_GET))
				$_GET=$this->stripSlashes($_GET);
			if(isset($_POST))
				$_POST=$this->stripSlashes($_POST);
			if(isset($_REQUEST))
				$_REQUEST=$this->stripSlashes($_REQUEST);
			if(isset($_COOKIE))
				$_COOKIE=$this->stripSlashes($_COOKIE);
		}
		if($this->enableCsrfValidation)
			Yii::app()->attachEventHandler('onBeginRequest',array($this,'validateCsrfToken'));
	}
	public function stripSlashes(&$data)
	{
		return is_array($data)?array_map(array($this,'stripSlashes'),$data):stripslashes($data);
	}
	public function getParam($name,$defaultValue=null)
	{
		return isset($_GET[$name]) ? $_GET[$name] : (isset($_POST[$name]) ? $_POST[$name] : $defaultValue);
	}
	public function getQuery($name,$defaultValue=null)
	{
		return isset($_GET[$name]) ? $_GET[$name] : $defaultValue;
	}
	public function getPost($name,$defaultValue=null)
	{
		return isset($_POST[$name]) ? $_POST[$name] : $defaultValue;
	}
	public function getDelete($name,$defaultValue=null)
	{
		if($this->_deleteParams===null)
			$this->_deleteParams=$this->getIsDeleteRequest() ? $this->getRestParams() : array();
		return isset($this->_deleteParams[$name]) ? $this->_deleteParams[$name] : $defaultValue;
	}
	public function getPut($name,$defaultValue=null)
	{
		if($this->_putParams===null)
			$this->_putParams=$this->getIsPutRequest() ? $this->getRestParams() : array();
		return isset($this->_putParams[$name]) ? $this->_putParams[$name] : $defaultValue;
	}
	protected function getRestParams()
	{
		$result=array();
		if(function_exists('mb_parse_str'))
			mb_parse_str(file_get_contents('php://input'), $result);
		else
			parse_str(file_get_contents('php://input'), $result);
		return $result;
	}
	public function getUrl()
	{
		return $this->getRequestUri();
	}
	public function getHostInfo($schema='')
	{
		if($this->_hostInfo===null)
		{
			if($secure=$this->getIsSecureConnection())
				$http='https';
			else
				$http='http';
			if(isset($_SERVER['HTTP_HOST']))
				$this->_hostInfo=$http.'://'.$_SERVER['HTTP_HOST'];
			else
			{
				$this->_hostInfo=$http.'://'.$_SERVER['SERVER_NAME'];
				$port=$secure ? $this->getSecurePort() : $this->getPort();
				if(($port!==80 && !$secure) || ($port!==443 && $secure))
					$this->_hostInfo.=':'.$port;
			}
		}
		if($schema!=='')
		{
			$secure=$this->getIsSecureConnection();
			if($secure && $schema==='https' || !$secure && $schema==='http')
				return $this->_hostInfo;
			$port=$schema==='https' ? $this->getSecurePort() : $this->getPort();
			if($port!==80 && $schema==='http' || $port!==443 && $schema==='https')
				$port=':'.$port;
			else
				$port='';
			$pos=strpos($this->_hostInfo,':');
			return $schema.substr($this->_hostInfo,$pos,strcspn($this->_hostInfo,':',$pos+1)+1).$port;
		}
		else
			return $this->_hostInfo;
	}
	public function setHostInfo($value)
	{
		$this->_hostInfo=rtrim($value,'/');
	}
	public function getBaseUrl($absolute=false)
	{
		if($this->_baseUrl===null)
			$this->_baseUrl=rtrim(dirname($this->getScriptUrl()),'\\/');
		return $absolute ? $this->getHostInfo() . $this->_baseUrl : $this->_baseUrl;
	}
	public function setBaseUrl($value)
	{
		$this->_baseUrl=$value;
	}
	public function getScriptUrl()
	{
		if($this->_scriptUrl===null)
		{
			$scriptName=basename($_SERVER['SCRIPT_FILENAME']);
			if(basename($_SERVER['SCRIPT_NAME'])===$scriptName)
				$this->_scriptUrl=$_SERVER['SCRIPT_NAME'];
			else if(basename($_SERVER['PHP_SELF'])===$scriptName)
				$this->_scriptUrl=$_SERVER['PHP_SELF'];
			else if(isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME'])===$scriptName)
				$this->_scriptUrl=$_SERVER['ORIG_SCRIPT_NAME'];
			else if(($pos=strpos($_SERVER['PHP_SELF'],'/'.$scriptName))!==false)
				$this->_scriptUrl=substr($_SERVER['SCRIPT_NAME'],0,$pos).'/'.$scriptName;
			else if(isset($_SERVER['DOCUMENT_ROOT']) && strpos($_SERVER['SCRIPT_FILENAME'],$_SERVER['DOCUMENT_ROOT'])===0)
				$this->_scriptUrl=str_replace('\\','/',str_replace($_SERVER['DOCUMENT_ROOT'],'',$_SERVER['SCRIPT_FILENAME']));
			else
				throw new CException(Yii::t('yii','CHttpRequest is unable to determine the entry script URL.'));
		}
		return $this->_scriptUrl;
	}
	public function setScriptUrl($value)
	{
		$this->_scriptUrl='/'.trim($value,'/');
	}
	public function getPathInfo()
	{
		if($this->_pathInfo===null)
		{
			$pathInfo=$this->getRequestUri();
			if(($pos=strpos($pathInfo,'?'))!==false)
			   $pathInfo=substr($pathInfo,0,$pos);
			$pathInfo=urldecode($pathInfo);
			$scriptUrl=$this->getScriptUrl();
			$baseUrl=$this->getBaseUrl();
			if(strpos($pathInfo,$scriptUrl)===0)
				$pathInfo=substr($pathInfo,strlen($scriptUrl));
			else if($baseUrl==='' || strpos($pathInfo,$baseUrl)===0)
				$pathInfo=substr($pathInfo,strlen($baseUrl));
			else if(strpos($_SERVER['PHP_SELF'],$scriptUrl)===0)
				$pathInfo=substr($_SERVER['PHP_SELF'],strlen($scriptUrl));
			else
				throw new CException(Yii::t('yii','CHttpRequest is unable to determine the path info of the request.'));
			$this->_pathInfo=trim($pathInfo,'/');
		}
		return $this->_pathInfo;
	}
	public function getRequestUri()
	{
		if($this->_requestUri===null)
		{
			if(isset($_SERVER['HTTP_X_REWRITE_URL'])) // IIS
				$this->_requestUri=$_SERVER['HTTP_X_REWRITE_URL'];
			else if(isset($_SERVER['REQUEST_URI']))
			{
				$this->_requestUri=$_SERVER['REQUEST_URI'];
				if(isset($_SERVER['HTTP_HOST']))
				{
					if(strpos($this->_requestUri,$_SERVER['HTTP_HOST'])!==false)
						$this->_requestUri=preg_replace('/^\w+:\/\/[^\/]+/','',$this->_requestUri);
				}
				else
					$this->_requestUri=preg_replace('/^(http|https):\/\/[^\/]+/i','',$this->_requestUri);
			}
			else if(isset($_SERVER['ORIG_PATH_INFO']))  // IIS 5.0 CGI
			{
				$this->_requestUri=$_SERVER['ORIG_PATH_INFO'];
				if(!empty($_SERVER['QUERY_STRING']))
					$this->_requestUri.='?'.$_SERVER['QUERY_STRING'];
			}
			else
				throw new CException(Yii::t('yii','CHttpRequest is unable to determine the request URI.'));
		}
		return $this->_requestUri;
	}
	public function getQueryString()
	{
		return isset($_SERVER['QUERY_STRING'])?$_SERVER['QUERY_STRING']:'';
	}
	public function getIsSecureConnection()
	{
		return isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'],'on');
	}
	public function getRequestType()
	{
		return strtoupper(isset($_SERVER['REQUEST_METHOD'])?$_SERVER['REQUEST_METHOD']:'GET');
	}
	public function getIsPostRequest()
	{
		return isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'],'POST');
	}
	public function getIsDeleteRequest()
	{
		return isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'],'DELETE');
	}
	public function getIsPutRequest()
	{
		return isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'],'PUT');
	}
	public function getIsAjaxRequest()
	{
		return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest';
	}
	public function getServerName()
	{
		return $_SERVER['SERVER_NAME'];
	}
	public function getServerPort()
	{
		return $_SERVER['SERVER_PORT'];
	}
	public function getUrlReferrer()
	{
		return isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:null;
	}
	public function getUserAgent()
	{
		return isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:null;
	}
	public function getUserHostAddress()
	{
		return isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:'127.0.0.1';
	}
	public function getUserHost()
	{
		return isset($_SERVER['REMOTE_HOST'])?$_SERVER['REMOTE_HOST']:null;
	}
	public function getScriptFile()
	{
		if($this->_scriptFile!==null)
			return $this->_scriptFile;
		else
			return $this->_scriptFile=realpath($_SERVER['SCRIPT_FILENAME']);
	}
	public function getBrowser($userAgent=null)
	{
		return get_browser($userAgent,true);
	}
	public function getAcceptTypes()
	{
		return isset($_SERVER['HTTP_ACCEPT'])?$_SERVER['HTTP_ACCEPT']:null;
	}
	private $_port;
	public function getPort()
	{
		if($this->_port===null)
			$this->_port=!$this->getIsSecureConnection() && isset($_SERVER['SERVER_PORT']) ? (int)$_SERVER['SERVER_PORT'] : 80;
		return $this->_port;
	}
	public function setPort($value)
	{
		$this->_port=(int)$value;
		$this->_hostInfo=null;
	}
	private $_securePort;
	public function getSecurePort()
	{
		if($this->_securePort===null)
			$this->_securePort=$this->getIsSecureConnection() && isset($_SERVER['SERVER_PORT']) ? (int)$_SERVER['SERVER_PORT'] : 443;
		return $this->_securePort;
	}
	public function setSecurePort($value)
	{
		$this->_securePort=(int)$value;
		$this->_hostInfo=null;
	}
	public function getCookies()
	{
		if($this->_cookies!==null)
			return $this->_cookies;
		else
			return $this->_cookies=new CCookieCollection($this);
	}
	public function redirect($url,$terminate=true,$statusCode=302)
	{
		if(strpos($url,'/')===0)
			$url=$this->getHostInfo().$url;
		header('Location: '.$url, true, $statusCode);
		if($terminate)
			Yii::app()->end();
	}
	public function getPreferredLanguage()
	{
		if($this->_preferredLanguage===null)
		{
			if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && ($n=preg_match_all('/([\w\-_]+)\s*(;\s*q\s*=\s*(\d*\.\d*))?/',$_SERVER['HTTP_ACCEPT_LANGUAGE'],$matches))>0)
			{
				$languages=array();
				for($i=0;$i<$n;++$i)
					$languages[$matches[1][$i]]=empty($matches[3][$i]) ? 1.0 : floatval($matches[3][$i]);
				arsort($languages);
				foreach($languages as $language=>$pref)
					return $this->_preferredLanguage=CLocale::getCanonicalID($language);
			}
			return $this->_preferredLanguage=false;
		}
		return $this->_preferredLanguage;
	}
	public function sendFile($fileName,$content,$mimeType=null,$terminate=true)
	{
		if($mimeType===null)
		{
			if(($mimeType=CFileHelper::getMimeTypeByExtension($fileName))===null)
				$mimeType='text/plain';
		}
		header('Pragma: public');
		header('Expires: 0');
		header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
		header("Content-type: $mimeType");
		if(ini_get("output_handler")=='')
			header('Content-Length: '.(function_exists('mb_strlen') ? mb_strlen($content,'8bit') : strlen($content)));
		header("Content-Disposition: attachment; filename=\"$fileName\"");
		header('Content-Transfer-Encoding: binary');
		if($terminate)
		{
			// clean up the application first because the file downloading could take long time
			// which may cause timeout of some resources (such as DB connection)
			Yii::app()->end(0,false);
			echo $content;
			exit(0);
		}
		else
			echo $content;
	}
	public function xSendFile($filePath, $options=array())
	{
		if(!is_file($filePath))
			return false;
		if(!isset($options['saveName']))
			$options['saveName']=basename($filePath);
		if(!isset($options['mimeType']))
		{
			if(($options['mimeType']=CFileHelper::getMimeTypeByExtension($filePath))===null)
				$options['mimeType']='text/plain';
		}
		if(!isset($options['xHeader']))
			$options['xHeader']='X-Sendfile';
		header('Content-type: '.$options['mimeType']);
		header('Content-Disposition: attachment; filename="'.$options['saveName'].'"');
		header(trim($options['xHeader']).': '.$filePath);
		if(!isset($options['terminate']) || $options['terminate'])
			Yii::app()->end();
		return true;
	}
	public function getCsrfToken()
	{
		if($this->_csrfToken===null)
		{
			$cookie=$this->getCookies()->itemAt($this->csrfTokenName);
			if(!$cookie || ($this->_csrfToken=$cookie->value)==null)
			{
				$cookie=$this->createCsrfCookie();
				$this->_csrfToken=$cookie->value;
				$this->getCookies()->add($cookie->name,$cookie);
			}
		}
		return $this->_csrfToken;
	}
	protected function createCsrfCookie()
	{
		$cookie=new CHttpCookie($this->csrfTokenName,sha1(uniqid(mt_rand(),true)));
		if(is_array($this->csrfCookie))
		{
			foreach($this->csrfCookie as $name=>$value)
				$cookie->$name=$value;
		}
		return $cookie;
	}
	public function validateCsrfToken($event)
	{
		if($this->getIsPostRequest())
		{
			// only validate POST requests
			$cookies=$this->getCookies();
			if($cookies->contains($this->csrfTokenName) && isset($_POST[$this->csrfTokenName]))
			{
				$tokenFromCookie=$cookies->itemAt($this->csrfTokenName)->value;
				$tokenFromPost=$_POST[$this->csrfTokenName];
				$valid=$tokenFromCookie===$tokenFromPost;
			}
			else
				$valid=false;
			if(!$valid)
				throw new CHttpException(400,Yii::t('yii','The CSRF token could not be verified.'));
		}
	}
}

request操作的相關方法,一目瞭然。
	public function init()
	{
		parent::init();
		$this->normalizeRequest();
	}
	protected function normalizeRequest()
	{
		// normalize request
		if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
		{
			if(isset($_GET))
				$_GET=$this->stripSlashes($_GET);
			if(isset($_POST))
				$_POST=$this->stripSlashes($_POST);
			if(isset($_REQUEST))
				$_REQUEST=$this->stripSlashes($_REQUEST);
			if(isset($_COOKIE))
				$_COOKIE=$this->stripSlashes($_COOKIE);
		}
		if($this->enableCsrfValidation)
			Yii::app()->attachEventHandler('onBeginRequest',array($this,'validateCsrfToken'));
	}
	public function stripSlashes(&$data)
	{
		return is_array($data)?array_map(array($this,'stripSlashes'),$data):stripslashes($data);
	}

可以看到yii對$_GET\$_POST\$_REQUEST\$_COOKIE進行了必要的過濾處理,所以可以放心的使用資料。

常用的有如下方法:

獲取get引數 public function getParam($name,$defaultValue=null)

 
獲取get引數public function getQuery($name,$defaultValue=null)
 
獲取post資料public function getPost($name,$defaultValue=null)
 
獲取請求的url public function getUrl()
 
獲取主機資訊public function getHostInfo($schema='')
 
設定                       public function setHostInfo($value)
 
獲取根目錄public function getBaseUrl($absolute=false)
 
獲取當前urlpublic function getScriptUrl()
 
獲取請求的url 

public function getRequestUri()
 
獲取querystringpublic function getQueryString()
 
判斷是否是httpspublic function getIsSecureConnection()
 
獲取請求型別public function getRequestType()
 
是否是post請求public function getIsPostRequest()
 
  
是否是ajax請求public function getIsAjaxRequest()
 
獲取伺服器名稱public function getServerName()
 
獲取服務埠public function getServerPort()
 
獲取引用路徑public function getUrlReferrer()
 
 
獲取使用者ip地址public function getUserHostAddress()
 
獲取使用者主機名稱public function getUserHost()
 
獲取執行指令碼名稱public function getScriptFile()
  
獲取cookiepublic function getCookies()
 
重定向public function redirect($url,$terminate=true,$statusCode=302)
 
設定下載檔案頭public function sendFile($fileName,$content,$mimeType=null,$terminate=true)
{
if($mimeType===null)
{
if(($mimeType=CFileHelper::getMimeTypeByExtension($fileName))===null)
$mimeType='text/plain';
}
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-type: $mimeType");
if(ini_get("output_handler")=='')
header('Content-Length: '.(function_exists('mb_strlen') ? mb_strlen($content,'8bit') : strlen($content)));
header("Content-Disposition: attachment; filename=\"$fileName\"");
header('Content-Transfer-Encoding: binary');
if($terminate)
{
// clean up the application first because the file downloading could take long time
// which may cause timeout of some resources (such as DB connection)
Yii::app()->end(0,false);
echo $content;
exit(0);
}
else
echo $content;
}
public function xSendFile($filePath, $options=array())
{
if(!is_file($filePath))
return false;
if(!isset($options['saveName']))
$options['saveName']=basename($filePath);
if(!isset($options['mimeType']))
{
if(($options['mimeType']=CFileHelper::getMimeTypeByExtension($filePath))===null)
$options['mimeType']='text/plain';
}
if(!isset($options['xHeader']))
$options['xHeader']='X-Sendfile';
header('Content-type: '.$options['mimeType']);
header('Content-Disposition: attachment; filename="'.$options['saveName'].'"');
header(trim($options['xHeader']).': '.$filePath);
if(!isset($options['terminate']) || $options['terminate'])
Yii::app()->end();
return true;
}

為了防止csrf,yii提供了相應的方法

CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。

public function getCsrfToken()
{
if($this->_csrfToken===null)
{
$cookie=$this->getCookies()->itemAt($this->csrfTokenName);
if(!$cookie || ($this->_csrfToken=$cookie->value)==null)
{
$cookie=$this->createCsrfCookie();
$this->_csrfToken=$cookie->value;
$this->getCookies()->add($cookie->name,$cookie);
}
}
return $this->_csrfToken;
}
protected function createCsrfCookie()
{
$cookie=new CHttpCookie($this->csrfTokenName,sha1(uniqid(mt_rand(),true)));
if(is_array($this->csrfCookie))
{
foreach($this->csrfCookie as $name=>$value)
$cookie->$name=$value;
}
return $cookie;
}
public function validateCsrfToken($event)
{
if($this->getIsPostRequest())
{
// only validate POST requests
$cookies=$this->getCookies();
if($cookies->contains($this->csrfTokenName) && isset($_POST[$this->csrfTokenName]))
{
$tokenFromCookie=$cookies->itemAt($this->csrfTokenName)->value;
$tokenFromPost=$_POST[$this->csrfTokenName];
$valid=$tokenFromCookie===$tokenFromPost;
}
else
$valid=false;
if(!$valid)
throw new CHttpException(400,Yii::t('yii','The CSRF token could not be verified.'));
}
}

對於$_GET的使用,不僅僅可以使用$_GET和以上提供的相關方法,在action中,可以繫結到action的方法引數。

這裡就一併羅列官方給出的說明。

從版本 1.1.4 開始,Yii 提供了對自動動作引數繫結的支援。 就是說,控制器動作可以定義命名的引數,引數的值將由 Yii 自動從 $_GET 填充。

為了詳細說明此功能,假設我們需要為 PostController 寫一個 create 動作。此動作需要兩個引數:

  • category: 一個整數,代表帖子(post)要發表在的那個分類的ID。
  • language: 一個字串,代表帖子所使用的語言程式碼。

從 $_GET 中提取引數時,我們可以不再下面這種無聊的程式碼了:

class PostController extends CController
{
    public function actionCreate()
    {
        if(isset($_GET['category']))
            $category=(int)$_GET['category'];
        else
            throw new CHttpException(404,'invalid request');
 
        if(isset($_GET['language']))
            $language=$_GET['language'];
        else
            $language='en';
 
        // ... fun code starts here ...
    }
}

現在使用動作引數功能,我們可以更輕鬆的完成任務:

class PostController extends CController
{
    public function actionCreate($category, $language='en')
    {
        $category=(int)$category;
 
        // ... fun code starts here ...
    }
}

注意我們在動作方法 actionCreate 中添加了兩個引數。 這些引數的名字必須和我們想要從 $_GET 中提取的名字一致。 當用戶沒有在請求中指定 $language 引數時,這個引數會使用預設值 en 。 由於 $category 沒有預設值,如果使用者沒有在 $_GET 中提供 category 引數, 將會自動丟擲一個 CHttpException (錯誤程式碼 400) 異常。 Starting from version 1.1.5, Yii also supports array type detection for action parameters. This is done by PHP type hinting using the syntax like the following:

class PostController extends CController
{
    public function actionCreate(array $categories)
    {
        // Yii will make sure $categories be an array
    }
}

That is, we add the keyword array in front of $categories in the method parameter declaration. By doing so, if $_GET['categories'] is a simple string, it will be converted into an array consisting of that string.

Note: If a parameter is declared without the array type hint, it means the parameter must be a scalar (i.e., not an array). In this case, passing in an array parameter via $_GET would cause an HTTP exception.


request的使用你只要保持和以前在php中的使用方式一樣,在yii中是不會出錯的