#定義
接下來要講的是控制器,MVC中的C。
一般來說,ThinkPHP的控制器是一個類,而操作則是控制器類的一個公共方法。
下面就是一個典型的控制器類的定義:
~~~
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
public function hello(){
echo 'hello,thinkphp!';
}
}
~~~
`Home\IndexController`類就代表了Home模塊下的Index控制器,而hello操作就是`Home\IndexController`類的hello(公共)方法。
當訪問 `http://serverName/index.php/Home/Index/hello` 后會輸出:
hello,thinkphp!
控制器通常需要繼承系統的Controller類或者其子類
控制器的名稱采用駝峰法命名(首字母大寫),控制器文件位于 `Home/Controller/IndexController.class.php`。
`IndexController`控制器類的hello方法就是操作方法,訪問下面的URL地址:
`http://serverName/Home/Index/hello`
會輸出
hello
操作方法的定義必須是公共方法,否則會報操作錯誤
##實例化控制器
訪問控制器的實例化通常是自動完成的,系統會根據URL地址解析出訪問的控制器名稱自動實例化,并且調用相關的操作方法。
如果你需要跨控制器調用的話,則可以單獨實例化:
// 實例化Home模塊的User控制器
$User = new \Home\Controller\UserController();
// 實例化Admin模塊的Blog控制器
$Blog = new \Admin\Controller\BlogController();
系統為上面的控制器實例化提供了一個快捷調用方法A,上面的代碼可以簡化為:
// 假設當前模塊是Home模塊
$User = A('User');
$Blog = A('Admin/Blog');
默認情況下,A方法實例化的是默認控制器層(Controller),如果你要實例化其他的分層控制器的話,可以使用:
// 假設當前模塊是Home模塊
// 實例化Event控制器
$User = A('User','Event');
$Blog = A('Admin/Blog','Event');
上面的代碼等效于:
// 實例化Home模塊的User事件控制器
$User = new \Home\Event\UserEvent();
// 實例化Admin模塊的Blog事件控制器
$Blog = new \Admin\Event\BlogEvent();
# 影響控制器方法進入的因素
## 偽靜態
URL偽靜態通常是為了滿足更好的SEO效果,ThinkPHP支持偽靜態URL設置,可以通過設置`URL_HTML_SUFFIX`參數隨意在URL的最后增加你想要的靜態后綴,而不會影響當前操作的正常執行。例如,我們設置
'URL_HTML_SUFFIX'=>'shtml'
的話,我們可以把下面的URL http://serverName/Home/Blog/read/id/1 變成 http://serverName/Home/Blog/read/id/1.shtml
后者更具有靜態頁面的URL特征,但是具有和前面的URL相同的執行效果,并且不會影響原來參數的使用。
默認情況下,偽靜態的設置為_html_,
如果我們設置偽靜態后綴為空
'URL_HTML_SUFFIX'=>''
則可以支持所有的靜態后綴,并且會記錄當前的偽靜態后綴到常量 __EXT__ ,但不會影響正常的頁面訪問。
例如:
~~~
http://serverName/Home/blog/3.html
http://serverName/Home/blog/3.shtml
http://serverName/Home/blog/3.xml
http://serverName/Home/blog/3.pdf
~~~
都可以正常訪問,如果要獲取當前的偽靜態后綴,通過常量 __EXT__ 獲取即可。
如果希望支持多個偽靜態后綴,可以直接設置如下:
~~~
// 多個偽靜態后綴設置 用|分割
'URL_HTML_SUFFIX' => 'html|shtml|xml'
~~~
那么,當訪問 `http://serverName/Home/blog/3.pdf` 的時候會報系統錯誤。
可以設置禁止訪問的URL后綴,例如:
~~~
'URL_DENY_SUFFIX' => 'pdf|ico|png|gif|jpg', // URL禁止訪問的后綴設置
~~~
如果訪問 `http://serverName/Home/blog/3.pdf` 就會直接返回404錯誤。
> 注意:
>`URL_DENY_SUFFIX`的優先級比`URL_HTML_SUFFIX`要高。
另外
>偽靜態和靜態頁面緩存是兩個不一樣的概念
## URL大小寫
系統默認的規范是根據URL里面的模塊名、控制器名來定位到具體的控制器類的,從而執行控制器類的操作方法。
以URL訪問 `http://serverName/index.php/Home/Index/index` 為例,其實訪問的控制器類文件是:
`Application/Home/Controller/IndexController.class.php`
如果是Windows環境,無論大小寫如何都能定位到`IndexController.class.php`文件,所以下面的訪問都是有效的:
~~~
http://serverName/index.php/Home/Index/index
http://serverName/index.php/Home/index/index
http://serverName/index.php/home/index/Index
~~~
如果在Linux環境下面,一旦大小寫不一致,就會發生URL里面使用小寫模塊名不能找到模塊類的情況。例如在Linux環境下面,我們訪問 `http://serverName/index.php/home/index/index` 其實請求的控制器文件是
`Application/home/Controller/indexController.class.php`
因為,我們定義的控制器類是IndexController而不是indexController(參考ThinkPHP的命名規范),由于Linux的文件特性,其實是不存在indexController控制器文件的,就會出現Index控制器不存在的錯誤,這樣的問題會造成用戶體驗的下降。
但是系統本身提供了一個不區分URL大小寫的解決方案,可以通過配置簡單實現。
只要在項目配置中,增加:
`'URL_CASE_INSENSITIVE' =>true`
配置好后,即使是在Linux環境下面,也可以實現URL訪問不再區分大小寫了。
~~~
http://serverName/index.php/Home/Index/index
// 將等效于
http://serverName/index.php/home/index/index
~~~
這里需要注意一個地方,一旦開啟了不區分URL大小寫后,如果我們要訪問類似UserTypeController的控制器,那么正確的URL訪問應該是:
~~~
// 正確的訪問地址
http://serverName/index.php/home/user_type/index
// 錯誤的訪問地址(linux環境下)
http://serverName/index.php/home/usertype/index
~~~
利用系統提供的U方法可以為你自動生成相關的URL地址。
如果設置
~~~
'URL_CASE_INSENSITIVE' =>false
~~~
的話,URL就又變成: `http://serverName/index.php/Home/UserType/add`
> 注意:URL不區分大小寫并不會改變系統的命名規范,并且只有按照系統的命名規范后才能正確的實現URL不區分大小寫。
### 如何知道是URL大小寫導致的問題呢?
首先,我們url錯誤了訪問會報錯,即使沒開調試模式,日志里也會記錄報錯。
然后,當遇到“Windows下開發的應用部署到服務器上,就訪問不了”,首先我們要排除的可能原因就是大小寫問題了。
最后,為了保證我們寫的代碼具有良好的可移植性。開發過程中,建議我們關閉
`URL_CASE_INSENSITIVE` 這個配置。
## 路由
這個會在進階知識中講,大家只需要知道路由會影響訪問的控制器操作(執行誰?、是否帶隱形參數)
# 流程相關
## 前置與后置操作
前置和后置操作指的是在執行某個操作方法之前和之后會自動調用的方法,不過僅對訪問控制器有效。
> 其他的分層控制器層和內部調用控制器的情況下前置和后置操作是無效的。
系統會檢測當前操作是否具有前置和后置操作,如果存在就會按照順序執行,前置和后置操作的定義方式如下:
~~~
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller{
//前置操作方法
public function _before_index(){
echo 'before<br/>';
}
public function index(){
echo 'index<br/>';
}
//后置操作方法
public function _after_index(){
echo 'after<br/>';
}
}
~~~
如果我們訪問 `http://serverName/index.php/Home/Index/index`
結果會輸出
~~~
before
index
after
~~~
>前置和后置操作的注意事項如下:
>1. 如果當前的操作并沒有定義操作方法,而是直接渲染模板文件,那么如果定義了前置和后置方法的話,依然會生效。真正有模板輸出的可能僅僅是當前的操作,前置和后置操作一般情況是沒有任何輸出的。
>2. 需要注意的是,在有些方法里面使用了exit或者錯誤輸出之類的話 有可能不會再執行后置方法了。例如,如果在當前操作里面調用了系統Action的error方法,那么將不會再執行后置操作,但是不影響success方法的后置方法執行。
## 輸入變量
在Web開發過程中,我們經常需要獲取系統變量或者用戶提交的數據,這些變量數據錯綜復雜,而且一不小心就容易引起安全隱患,但是如果利用好ThinkPHP提供的變量獲取功能,就可以輕松的獲取和駕馭變量了。
### 獲取變量
雖然你仍然可以在開發過程中使用傳統方式獲取各種系統變量,例如
~~~
$id = $_GET['id']; // 獲取get變量
$name = $_POST['name']; // 獲取post變量
$value = $_SESSION['var']; // 獲取session變量
$name = $_COOKIE['name']; // 獲取cookie變量
$file = $_SERVER['PHP_SELF']; // 獲取server變量
~~~
但是我們不建議直接使用傳統方式獲取,因為沒有統一的安全處理機制,后期如果調整的話,改起來會比較麻煩。所以,更好的方式是在框架中統一使用I函數進行變量獲取和過濾。
I方法是ThinkPHP用于更加方便和安全的獲取系統輸入變量,可以用于任何地方,用法格式如下:
**I('變量類型.變量名/修飾符',['默認值'],['過濾方法'],['額外數據源'])**
變量類型是指請求方式或者輸入類型,包括:
|變量類型|含義|
|||
| get |獲取GET參數|
|post|獲取POST參數|
|param |自動判斷請求類型獲取GET、POST或者PUT參數|
|request|獲取REQUEST 參數|
|put |獲取PUT 參數|
|session|獲取 $_SESSION 參數|
|cookie |獲取 $_COOKIE 參數|
|server |獲取 $_SERVER 參數|
|globals|獲取 $GLOBALS參數|
|path|獲取 PATHINFO模式的URL參數(3.2.2新增)|
|data|獲取 其他類型的參數,需要配合額外數據源參數(3.2.2新增)|
>注意:變量類型不區分大小寫。
>變量名則嚴格區分大小寫。
>默認值和過濾方法均屬于可選參數。
>變量修飾符是3.2.3版本新增
我們以GET變量類型為例,說明下I方法的使用:
~~~
echo I('get.id'); // 相當于 $_GET['id']
echo I('get.name'); // 相當于 $_GET['name']
~~~
支持默認值:
~~~
echo I('get.id',0); // 如果不存在$_GET['id'] 則返回0
echo I('get.name',''); // 如果不存在$_GET['name'] 則返回空字符串
~~~
采用方法過濾:
~~~
// 采用htmlspecialchars方法對$_GET['name'] 進行過濾,如果不存在則返回空字符串
echo I('get.name','','htmlspecialchars');
~~~
支持直接獲取整個變量類型,例如:
~~~
// 獲取整個$_GET 數組
I('get.');
~~~
用同樣的方式,我們可以獲取post或者其他輸入類型的變量,例如:
~~~
I('post.name','','htmlspecialchars'); // 采用htmlspecialchars方法對$_POST['name'] 進行過濾,如果不存在則返回空字符串
I('session.user_id',0); // 獲取$_SESSION['user_id'] 如果不存在則默認為0
I('cookie.'); // 獲取整個 $_COOKIE 數組
I('server.REQUEST_METHOD'); // 獲取 $_SERVER['REQUEST_METHOD']
~~~
param變量類型是框架特有的支持自動判斷當前請求類型的變量獲取方式,例如:
echo I('param.id'); //相當于 I('request.id')
由于param類型是I函數默認獲取的變量類型,因此事實上param變量類型的寫法可以簡化為:
I('id'); // 等同于 I('param.id')
I('name'); // 等同于 I('param.name')
3.2.2新增了`path和data兩個變量類型`,用法如下:
path類型變量可以用于獲取URL參數(必須是PATHINFO模式參數有效,無論是GET還是POST方式都有效),例如: 當前訪問URL地址是
`http://serverName/index.php/New/2013/06/01`
那么我們可以通過
~~~
echo I('path.1'); // 輸出2013
echo I('path.2'); // 輸出06
echo I('path.3'); // 輸出01
~~~
data類型變量可以用于獲取不支持的變量類型的讀取,例如:
I('data.file1','','',$_FILES);
### 變量過濾
如果你沒有在調用I函數的時候指定過濾方法的話,系統會采用默認的過濾機制(由DEFAULT_FILTER配置),事實上,該參數的默認設置是:
~~~
// 系統默認的變量過濾機制
'DEFAULT_FILTER' => 'htmlspecialchars'
~~~
也就說,I方法的所有獲取變量如果沒有設置過濾方法的話都會進行`htmlspecialchars`過濾,那么:
~~~
// 等同于 htmlspecialchars($_GET['name'])
I('get.name');
~~~
同樣,該參數也可以設置支持多個過濾,例如:
`'DEFAULT_FILTER'=> 'strip_tags,htmlspecialchars'`
設置后,我們在使用:
~~~
// 等同于 htmlspecialchars(strip_tags($_GET['name']))
I('get.name');
~~~
如果我們在使用I方法的時候 指定了過濾方法,那么就會忽略DEFAULT_FILTER的設置,例如:
~~~
// 等同于 strip_tags($_GET['name'])
echo I('get.name','','strip_tags');
~~~
I方法的第三個參數如果傳入函數名,則表示調用該函數對變量進行過濾并返回(在變量是數組的情況下自動使用array_map進行過濾處理),否則會調用PHP內置的`filter_var`方法進行過濾處理,例如:
~~~
I('post.email','',FILTER_VALIDATE_EMAIL);
~~~
表示 會對`$_POST['email']` 進行 格式驗證,如果不符合要求的話,返回空字符串。 (關于更多的驗證格式,可以參考 官方手冊的filter_var用法。) 或者可以用下面的字符標識方式:
`I('post.email','','email');`
可以支持的過濾名稱必須是`filter_list`方法中的有效值(不同的服務器環境可能有所不同),可能支持的包括
~~~
int
boolean
float
validate_regexp
validate_url
validate_email
validate_ip
string
stripped
encoded
special_chars
unsafe_raw
email
url
number_int
number_float
magic_quotes
callback
~~~
3.2.3版本開始支持進行正則匹配過濾,例如:
~~~
// 采用正則表達式進行變量過濾
I('get.name','','/^[A-Za-z]+$/');
I('get.id',0,'/^\d+$/');
~~~
如果正則匹配不通過的話,則返回默認值。
在有些特殊的情況下,我們不希望進行任何過濾,即使DEFAULT_FILTER已經有所設置,可以使用
~~~
// 下面兩種方式都不采用任何過濾方法
I('get.name','','');
I('get.id','',false);
~~~
一旦過濾參數設置為空字符串或者false,即表示不再進行任何的過濾。
### 變量修飾符
3.2.3版本開始,I函數支持對變量使用修飾符功能,可以更好的過濾變量。
用法如下: **I('變量類型.變量名/修飾符')**;
例如:
~~~
I('get.id/d');
I('post.name/s');
I('post.ids/a');
~~~
可以使用的修飾符包括:
|修飾符 |作用|
|||
|s |強制轉換為字符串類型|
|d |強制轉換為整形類型|
|b |強制轉換為布爾類型|
|a |強制轉換為數組類型|
|f |強制轉換為浮點類型|
## 請求類型
在很多情況下面,我們需要判斷當前操作的請求類型是GET 、POST 、PUT或 DELETE,一方面可以針對請求類型作出不同的邏輯處理,另外一方面有些情況下面需要驗證安全性,過濾不安全的請求。 系統內置了一些**常量**用于判斷請求類型,包括:
|常量|說明|
|||
|IS_GET|判斷是否是GET方式提交|
|IS_POST|判斷是否是POST方式提交|
|IS_PUT|判斷是否是PUT方式提交|
|IS_DELETE|判斷是否是DELETE方式提交|
|IS_AJAX|判斷是否是AJAX提交|
|REQUEST_METHOD|當前提交類型|
使用舉例如下:
~~~
class UserController extends Controller{
public function update(){
if (IS_POST){
$User = M('User');
$User->create();
$User->save();
$this->success('保存完成');
}else{
$this->error('非法請求');
}
}
}
~~~
> 需要注意的是,如果使用的是ThinkAjax或者自己寫的Ajax類庫的話,需要在表單里面添加一個隱藏域,告訴后臺屬于ajax方式提交,默認的隱藏域名稱是ajax(可以通過VAR_AJAX_SUBMIT配置),如果是JQUERY類庫的話,則無需添加任何隱藏域即可自動判斷。
## 空操作
空操作是指系統在找不到請求的操作方法的時候,會定位到空操作(`_empty`)方法來執行,利用這個機制,我們可以實現錯誤頁面和一些URL的優化。
例如,下面我們用空操作功能來實現一個城市切換的功能。 我們只需要給CityController類定義一個`_empty`(空操作)方法:
~~~
<?php
namespace Home\Controller;
use Think\Controller;
class CityController extends Controller{
public function _empty($name){
//把所有城市的操作解析到city方法
$this->city($name);
}
//注意 city方法 本身是 protected 方法
protected function city($name){
//和$name這個城市相關的處理
echo '當前城市' . $name;
}
}
~~~
接下來,我們就可以在瀏覽器里面輸入
http://serverName/index.php/Home/City/beijing/
http://serverName/index.php/Home/City/shanghai/
http://serverName/index.php/Home/City/shenzhen/
由于City控制器并沒有定義beijing、shanghai或者shenzhen操作方法,因此系統會定位到空操作方法 `_empty`中去解析,`_empty`方法的參數就是當前URL里面的操作名,因此會看到依次輸出的結果是:
~~~
當前城市:beijing
當前城市:shanghai
當前城市:shenzhen
~~~
> 注意:空操作方法僅在你的控制器類繼承系統的Think\Controller類才有效,否則需要自己定義 __call 來實現。
這個空操作的應用場景有哪些呢?
- 錯誤處理
- 單頁處理(比如企業單頁-關于我們之類的實現)
- 一些接口動態方法的處理,如微博、微信
- 縮短url
## 空控制器
空控制器的概念是指當系統找不到請求的控制器名稱的時候,系統會嘗試定位空控制器(EmptyController),利用這個機制我們可以用來定制錯誤頁面和進行URL的優化。
現在我們把前面的需求進一步,把URL由原來的
`http://serverName/index.php/Home/City/shanghai/`
變成
`http://serverName/index.php/Home/shanghai/`
這樣更加簡單的方式,如果按照傳統的模式,我們必須給每個城市定義一個控制器類,然后在每個控制器類的index方法里面進行處理。可是如果使用空控制器功能,這個問題就可以迎刃而解了。
我們可以給項目定義一個EmptyController類
~~~
<?php
namespace Home\Controller;
use Think\Controller;
class EmptyController extends Controller{
public function index(){
//根據當前控制器名來判斷要執行那個城市的操作
$cityName = CONTROLLER_NAME;
$this->city($cityName);
}
//注意 city方法 本身是 protected 方法
protected function city($name){
//和$name這個城市相關的處理
echo '當前城市' . $name;
}
}
~~~
接下來,我們就可以在瀏覽器里面輸入
~~~
http://serverName/index.php/Home/beijing/
http://serverName/index.php/Home/shanghai/
http://serverName/index.php/Home/shenzhen/
~~~
由于系統并不存在beijing、shanghai或者shenzhen控制器,因此會定位到空控制器(EmptyController)去執行,會看到依次輸出的結果是:
~~~
當前城市:beijing
當前城市:shanghai
當前城市:shenzhen
~~~
> 空控制器和空操作還可以同時使用,用以完成更加復雜的操作。
# 控制器相關的輸出
## URL生成
為了配合所使用的URL模式,我們需要能夠動態的根據當前的URL設置生成對應的URL地址,為此,ThinkPHP內置提供了U方法,用于URL的動態生成,可以確保項目在移植過程中不受環境的影響。
### 定義規則
U方法的定義規則如下(方括號內參數根據實際應用決定):
**U('地址表達式',['參數'],['偽靜態后綴'],['顯示域名'])**
#### 地址表達式
地址表達式的格式定義如下:
~~~
[模塊/控制器/操作#錨點@域名]?參數1=值1&參數2=值2...
~~~
如果不定義模塊的話 就表示當前模塊名稱,下面是一些簡單的例子:
~~~
U('User/add') // 生成User控制器的add操作的URL地址
U('Blog/read?id=1') // 生成Blog控制器的read操作 并且id為1的URL地址
U('Admin/User/select') // 生成Admin模塊的User控制器的select操作的URL地址
~~~
#### 參數
U方法的第二個參數支持數組和字符串兩種定義方式,如果只是字符串方式的參數可以在第一個參數中定義,例如:
~~~
U('Blog/cate',array('cate_id'=>1,'status'=>1))
U('Blog/cate','cate_id=1&status=1')
U('Blog/cate?cate_id=1&status=1')
~~~
三種方式是等效的,都是生成Blog控制器的cate操作 并且`cate_id`為1 `status`為1的URL地址。
但是不允許使用下面的定義方式來傳參數
`U('Blog/cate/cate_id/1/status/1');`
#### 偽靜態后綴
U函數會自動識別當前配置的偽靜態后綴,如果你需要指定后綴生成URL地址的話,可以顯式傳入,例如:
`U('Blog/cate','cate_id=1&status=1','xml');`
### 自動識別
根據項目的不同URL設置,同樣的U方法調用可以智能地對應產生不同的URL地址效果,例如針對:
`U('Blog/read?id=1');`
這個定義為例。
如果當前URL設置為普通模式的話,最后生成的URL地址是:
`http://serverName/index.php?m=Blog&a=read&id=1`
如果當前URL設置為PATHINFO模式的話,同樣的方法最后生成的URL地址是:
`http://serverName/index.php/Home/Blog/read/id/1`
如果當前URL設置為REWRITE模式的話,同樣的方法最后生成的URL地址是:
~~~
http://serverName/Home/Blog/read/id/1
~~~
如果當前URL設置為REWRITE模式,并且設置了偽靜態后綴為.html的話,同樣的方法最后生成的URL地址是:
`http://serverName/Home/Blog/read/id/1.html`
> 如果開啟了`URL_CASE_INSENSITIVE`,則會統一生成小寫的URL地址。
### 生成路由地址
U方法還可以支持路由,如果我們定義了一個路由規則為:
`'news/:id\d'=>'News/read'`
那么可以使用
`U('/news/1');`
最終生成的URL地址是:
`http://serverName/index.php/Home/news/1`
> 注意:如果你是在模板文件中直接使用U方法的話,需要采用 {:U('參數1', '參數2'…)} 的方式,具體參考模板的使用函數內容。
### 域名支持
如果你的應用涉及到多個子域名的操作地址,那么也可以在U方法里面指定需要生成地址的域名,例如:
`U('Blog/read@blog.thinkphp.cn','id=1');`
@后面傳入需要指定的域名即可。
系統會自動判斷當前是否SSL協議,生成`https://`。
此外,U方法的第4個參數如果設置為true,表示自動識別當前的域名,并且會自動根據子域名部署設置`APP_SUB_DOMAIN_DEPLOY`和`APP_SUB_DOMAIN_RULES`自動匹配生成當前地址的子域名。
### 錨點支持
U函數可以直接生成URL地址中的錨點,例如:
~~~
U('Blog/read#comment?id=1');
~~~
生成的URL地址可能是:
`http://serverName/index.php/Home/Blog/read/id/1#comment`
## AJAX返回
ThinkPHP可以很好的支持AJAX請求,系統的`\Think\Controller`類提供了`ajaxReturn`方法用于AJAX調用后返回數據給客戶端。并且支持JSON、JSONP、XML和EVAL四種方式給客戶端接受數據,并且支持配置其他方式的數據格式返回。
ajaxReturn方法調用示例:
~~~
$data = 'ok';
$this->ajaxReturn($data);
~~~
支持返回數組數據:
~~~
$data['status'] = 1;
$data['content'] = 'content';
$this->ajaxReturn($data);
~~~
默認配置采用JSON格式返回數據(通過配置DEFAULT_AJAX_RETURN進行設置),我們可以指定格式返回,例如:
~~~
// 指定XML格式返回數據
$data['status'] = 1;
$data['content'] = 'content';
$this->ajaxReturn($data,'xml');
~~~
返回數據data可以支持字符串、數字和數組、對象,返回客戶端的時候根據不同的返回格式進行編碼后傳輸。如果是JSON/JSONP格式,會自動編碼成JSON字符串,如果是XML方式,會自動編碼成XML字符串,如果是EVAL方式的話,只會輸出字符串data數據。
> JSON和JSONP雖然只有一個字母的差別,但其實他們根本不是一回事兒:JSON是一種數據交換格式,而JSONP是一種非官方跨域數據交互協議。一個是描述信息的格式,一個是信息傳遞的約定方法。
默認的JSONP格式返回的處理方法是`jsonpReturn`,如果你采用不同的方法,可以設置:
~~~
'DEFAULT_JSONP_HANDLER' => 'myJsonpReturn', // 默認JSONP格式返回的處理方法
~~~
或者直接在頁面中用callback參數來指定。
> 除了上面四種返回類型外,我們還可以通過行為擴展來增加其他類型的支持,只需要對`ajax_return`標簽位進行行為綁定即可。
## 跳轉和重定向
### 頁面跳轉
在應用開發中,經常會遇到一些帶有提示信息的跳轉頁面,例如操作成功或者操作錯誤頁面,并且自動跳轉到另外一個目標頁面。系統的`\Think\Controller`類內置了兩個跳轉方法success和error,用于頁面跳轉提示,而且可以支持ajax提交。
使用方法很簡單,舉例如下:
~~~
$User = M('User'); //實例化User對象
$result = $User->add($data);
if($result){
//設置成功后跳轉頁面的地址,默認的返回頁面是$_SERVER['HTTP_REFERER']
$this->success('新增成功', 'User/list');
} else {
//錯誤頁面的默認跳轉頁面是返回前一頁,通常不需要設置
$this->error('新增失敗');
}
~~~
success和error方法的第一個參數表示提示信息,第二個參數表示跳轉地址,第三個參數是跳轉時間(單位為秒),例如:
~~~
// 操作完成3秒后跳轉到 /Article/index
$this->success('操作完成','/Article/index',3);
// 操作失敗5秒后跳轉到 /Article/error
$this->error('操作失敗','/Article/error',5);
~~~
跳轉地址是可選的,success方法的默認跳轉地址是`$_SERVER["HTTP_REFERER"]`,error方法的默認跳轉地址是`javascript:history.back(-1);`。
> 默認的等待時間success方法是1秒,error方法是3秒
`success`和`error`方法都可以對應的模板,默認的設置是兩個方法對應的模板都是:
~~~
//默認錯誤跳轉對應的模板文件
'TMPL_ACTION_ERROR' => THINK_PATH . 'Tpl/dispatch_jump.tpl',
//默認成功跳轉對應的模板文件
'TMPL_ACTION_SUCCESS' => THINK_PATH . 'Tpl/dispatch_jump.tpl',
~~~
也可以使用項目內部的模板文件
~~~
//默認錯誤跳轉對應的模板文件
'TMPL_ACTION_ERROR' => 'Public:error';
//默認成功跳轉對應的模板文件
'TMPL_ACTION_SUCCESS' => 'Public:success';
~~~
模板文件可以使用模板標簽,并且可以使用下面的模板變量:
| 變量 | 含義 |
|-----|-----|
| $msgTitle | 操作標題 |
| $message | 頁面提示信息 |
| $status | 操作狀態 1表示成功 0 表示失敗 具體還可以由項目本身定義規則 |
| $waitSecond | 跳轉等待時間 單位為秒 |
| $jumpUrl | 跳轉頁面地址 |
success和error方法會自動判斷當前請求是否屬于Ajax請求,如果屬于Ajax請求則會調用ajaxReturn方法返回信息。 ajax方式下面,success和error方法會封裝下面的數據返回:
~~~
$data['info'] = $message; // 提示信息內容
$data['status'] = $status; // 狀態 如果是success是1 error 是0
$data['url'] = $jumpUrl; // 成功或者錯誤的跳轉地址
~~~
### 重定向
Controller類的redirect方法可以實現頁面的重定向功能。
redirect方法的參數用法和U函數的用法一致(參考[URL生成](1718)部分),例如:
~~~
//重定向到New模塊的Category操作
$this->redirect('New/category', array('cate_id' => 2), 5, '頁面跳轉中...');
~~~
上面的用法是停留5秒后跳轉到New模塊的category操作,并且顯示頁面跳轉中字樣,重定向后會改變當前的URL地址。
如果你僅僅是想重定向要一個指定的URL地址,而不是到某個模塊的操作方法,可以直接使用`redirect`函數重定向,例如:
~~~
//重定向到指定的URL地址
redirect('/New/category/cate_id/2', 5, '頁面跳轉中...')
~~~
Redirect函數的第一個參數是一個URL地址。
> 控制器的redirect方法和redirect函數的區別在于前者是用URL規則定義跳轉地址,后者是一個純粹的URL地址。
# 自行充電的可選項
## 插件控制器
## 操作綁定到類
# 總結
通過本章節,你應該能解決以下問題:
- 如何定義一個控制器
- 如何在控制器中引用任意控制器
- 知道有哪些因素會限制你訪問某控制器的某方法
- 知道如何控制控制器方法中的流程
- 知道如何生成你想要的URL
- 知道使用路由或空控制器和空操作來動態處理url
- 知道輸出模板或者你想要的格式如Json、或重定向
- 序
- 前言
- 內容簡介
- 目錄
- 基礎知識
- 起步
- 控制器
- 模型
- 模板
- 命名空間
- 進階知識
- 路由
- 配置
- 緩存
- 權限
- 擴展
- 國際化
- 安全
- 單元測試
- 拿來主義
- 調試方法
- 調試的步驟
- 調試工具
- 顯示trace信息
- 開啟調試和關閉調試的區別
- netbeans+xdebug
- Socketlog
- PHP常見錯誤
- 小黃鴨調試法,每個程序員都要知道的
- 應用場景
- 第三方登錄
- 圖片處理
- 博客
- SAE
- REST實踐
- Cli
- ajax分頁
- barcode條形碼
- excel
- 發郵件
- 漢字轉全拼和首字母,支持帶聲調
- 中文分詞
- 瀏覽器useragent解析
- freelog項目實戰
- 需求分析
- 數據庫設計
- 編碼實踐
- 前端實現
- rest接口
- 文章發布
- 文件上傳
- 視頻播放
- 音樂播放
- 圖片幻燈片展示
- 注冊和登錄
- 個人資料更新
- 第三方登錄的使用
- 后臺
- 微信的開發
- 首頁及個人主頁
- 列表
- 歸檔
- 搜索
- 分頁
- 總結經驗
- 自我提升
- 進行小項目的鍛煉
- 對現有輪子的重構和移植
- 寫技術博客
- 制作視頻教程
- 學習PHP的知識和新特性
- 和同行直接溝通、交流
- 學好英語,走向國際
- 如何參與
- 瀏覽官網和極思維還有看云
- 回答ThinkPHP新手的問題
- 嘗試發現ThinkPHP的bug,告訴官方人員或者push request
- 開發能提高效率的ThinkPHP工具
- 嘗試翻譯官方文檔
- 幫新手入門
- 創造基于ThinkPHP的產品,進行連帶推廣
- 展望未來
- OneThink
- ThinkPHP4
- 附錄