ThinkPHP3.2.3學習筆記1---控制器


ThinkPHP是為了簡化企業級應用開發和敏捷WEB應用開發而誕生的。最早誕生於2006年初,2007年元旦正式更名為ThinkPHP,並且遵循Apache2開源協議發布。ThinkPHP從誕生以來一直秉承簡潔實用的設計原則,在保持出色的性能和至簡的代碼的同時,也注重易用性。並且擁有眾多原創功能和特性,在社區團隊的積極參與下,在易用性、擴展性和性能方面不斷優化和改進。

ThinkPHP是一個快速、兼容而且簡單的輕量級國產PHP開發框架,誕生於2006年初,原名FCS,2007年元旦正式更名為ThinkPHP,遵循Apache2開源協議發布,從Struts結構移植過來並做了改進和完善,同時也借鑒了國外很多優秀的框架和模式,使用面向對象的開發結構和MVC模式,融合了Struts的思想和TagLib(標簽庫)、RoR的ORM映射和ActiveRecord模式。

ThinkPHP可以支持windows/Unix/Linux等服務器環境,正式版需要PHP5.0以上版本支持,支持MySql、PgSQL、Sqlite以及PDO等多種數據庫,ThinkPHP框架本身沒有什么特別模塊要求,具體的應用系統運行環境要求視開發所涉及的模塊。

作為一個整體開發解決方案,ThinkPHP能夠解決應用開發中的大多數需要,因為其自身包含了底層架構、兼容處理、基類庫、數據庫訪問層、模板引擎、緩存機制、插件機制、角色認證、表單處理等常用的組件,並且對於跨版本、跨平台和跨數據庫移植都比較方便。並且每個組件都是精心設計和完善的,應用開發過程僅僅需要關注您的業務邏輯。

Via: http://baike.baidu.com/view/908071.htm

 

ThinkPHP3.2完全開發手冊網址:http://document.thinkphp.cn/, TP框架的開發手冊寫得比較詳細,只要靜下心來學習,學會使用問題不大,如果想更加深入的學習,TP框架的源代碼最好能看懂,如果能做二次開發就更好了。

學習的時候心要安靜很重要,不能三心二意,心態不能浮躁,堅持下去,一定會有所收獲的。

 

一、定義控制器
Application/Home/Controller/IndexController.class.php

 1 <?php
 2 namespace Home\Controller;
 3 use Think\Controller;
 4 class UserController extends Controller {
 5     public function index(){
 6         //Home\Controller\UserController::index this is news controller Home\Controller\UserController
 7         echo __METHOD__ . ' this is news controller ' . __CLASS__;
 8     }
 9 }
10 ?>

 

Home\UserController類就代表了Home模塊下的User控制器,而index操作就是Home\IndexController類的index(公共)方法。
當訪問 http://serverName/Home/User/index or http://serverName/index.php/Home/User/index 后會輸出:
Home\Controller\UserController::index this is news controller Home\Controller\UserController


控制器的名稱采用駝峰法命名(首字母大寫), 操作方法的定義必須是公共方法,否則會報操作錯誤


二、設置操作方法的后綴
因為操作方法就是控制器的一個方法,所以遇到有和系統的關鍵字沖突的方法可能就不能定義了,這個時候我們可以設置操作方法的后綴來解決,例如:
'ACTION_SUFFIX' => 'Action', // 操作方法后綴

將'ACTION_SUFFIX' => 'Action',加入到文件Application/Home/Conf/config.php中

Application/Home/Controller/TestController.class.php

 1 <?php
 2 namespace Home\Controller;
 3 use Think\Controller;
 4 class TestController extends Controller {
 5     //http://localhost:81/research/thinkphp_3.2.3_full/Home/Test/hello
 6     public function helloAction(){
 7         echo __METHOD__ . ' hello';
 8     }
 9 
10     //http://localhost:81/research/thinkphp_3.2.3_full/Home/Test/test
11     public function testAction(){
12         echo __METHOD__ . ' test';
13     }
14 }
15 ?>

 

操作方法的后綴設置只是影響控制器類的定義,對URL訪問沒有影響。

訪問http://localhost:81/research/thinkphp_3.2.3_full/Home/Test/hello
輸出Home\Controller\TestController::helloAction hello

訪問http://localhost:81/research/thinkphp_3.2.3_full/Home/Test/test
輸出Home\Controller\TestController::testAction test


注意,將ACTION_SUFFIX設置為Action以后('ACTION_SUFFIX' => 'Action'),如果控制器類中的方法名稱后面不是Action,則訪問時系統會報錯。

例如
文件Application/Home/Controller/UserController.class.php內容如下:

 1 <?php
 2 namespace Home\Controller;
 3 use Think\Controller;
 4 class UserController extends Controller {
 5     public function index(){
 6         //Home\Controller\UserController::index this is news controller Home\Controller\UserController
 7         $str = 'inner ' . __METHOD__ . ' this is news controller ' . __CLASS__;
 8         echo $str;
 9     }
10 
11     public function getUser() {
12         return 'inner ' . __METHOD__ . ' zhangsan';
13     }
14 }
15 ?>

 

訪問http://localhost:81/research/thinkphp_3.2.3_full/Home/User/index
則報如下的錯誤:
--------
非法操作:index
錯誤位置
FILE: E:\myphp\research\thinkphp_3.2.3_full\ThinkPHP\Library\Think\Controller.class.php  LINE: 170
TRACE
#0 E:\myphp\research\thinkphp_3.2.3_full\ThinkPHP\Library\Think\Controller.class.php(170): E('????????????:in...')
#1 [internal function]: Think\Controller->__call('indexAction', '')
#2 E:\myphp\research\thinkphp_3.2.3_full\ThinkPHP\Library\Think\App.class.php(115): ReflectionMethod->invokeArgs(Object(Home\Controller\UserController), Array)
#3 E:\myphp\research\thinkphp_3.2.3_full\ThinkPHP\Library\Think\App.class.php(205): Think\App::exec()
#4 E:\myphp\research\thinkphp_3.2.3_full\ThinkPHP\Library\Think\Think.class.php(120): Think\App::run()
#5 E:\myphp\research\thinkphp_3.2.3_full\ThinkPHP\ThinkPHP.php(97): Think\Think::start()
#6 E:\myphp\research\thinkphp_3.2.3_full\index.php(24): require('E:\myphp\resear...')
#7 {main}
ThinkPHP3.2.3 { Fast & Simple OOP PHP Framework } -- [ WE CAN DO IT JUST THINK ]
--------

將方法名稱由index改為indexAction
訪問http://localhost:81/research/thinkphp_3.2.3_full/Home/User/index
輸出inner Home\Controller\UserController::indexAction this is news controller Home\Controller\UserController

總結:也就是說,控制器的方法名稱后面要么全部帶有Action,要么全部沒有Action,要統一, 將ACTION_SUFFIX設置為Action以后,不被url直接訪問的控制器名稱可以沒有Action,如上面的getUser方法。


三、多級控制器

多級控制器
多級控制器是指控制器可以通過子目錄把某個控制器層分組存放,首先需要設置控制器的分級層次,例如,我們設置2級目錄的控制器層:

'CONTROLLER_LEVEL' => 2,

將'CONTROLLER_LEVEL' => 2,加入到文件Application/Home/Conf/config.php中

Application/Home/Controller/News/NewsController.class.php

 1 <?php
 2 namespace Home\Controller\News;
 3 use Think\Controller;
 4 class NewsController extends Controller {
 5     public function helloAction(){
 6         echo __CLASS__ . ' hello';
 7     }
 8 
 9     public function testAction(){
10         echo __CLASS__ . ' test';
11     }
12 }
13 ?>

 

下面的url中第一個News表示目錄路徑,第二個News表示控制器名稱
訪問http://localhost:81/research/thinkphp_3.2.3_full/Home/News/News/hello
輸出Home\Controller\News\NewsController hello

將CONTROLLER_LEVEL設為2以后,原來放到控制根目錄(Application/Home/Controller)下的文件訪問的時候會報錯

訪問http://localhost:81/research/thinkphp_3.2.3_full/Home/Test/hello
會報如下的錯誤
---------
無法加載控制器:Test/hello
錯誤位置
FILE: E:\myphp\research\thinkphp_3.2.3_full\ThinkPHP\Library\Think\App.class.php  LINE: 102
TRACE
#0 E:\myphp\research\thinkphp_3.2.3_full\ThinkPHP\Library\Think\App.class.php(102): E('???????????????...')
#1 E:\myphp\research\thinkphp_3.2.3_full\ThinkPHP\Library\Think\App.class.php(205): Think\App::exec()
#2 E:\myphp\research\thinkphp_3.2.3_full\ThinkPHP\Library\Think\Think.class.php(120): Think\App::run()
#3 E:\myphp\research\thinkphp_3.2.3_full\ThinkPHP\ThinkPHP.php(97): Think\Think::start()
#4 E:\myphp\research\thinkphp_3.2.3_full\index.php(24): require('E:\myphp\resear...')
#5 {main}
ThinkPHP3.2.3 { Fast & Simple OOP PHP Framework } -- [ WE CAN DO IT JUST THINK ]
---------

總結:也就是說,控制器要么全部放在一級目錄下,要么放在二級目錄下,要統一。

 

四、實例化控制器
訪問控制器的實例化通常是自動完成的,系統會根據URL地址解析出訪問的控制器名稱自動實例化,並且調用相關的操作方法。

如果你需要跨控制器調用的話,則可以單獨實例化:

Application/Home/Controller/UserController.class.php

 1 <?php
 2 namespace Home\Controller;
 3 use Think\Controller;
 4 class UserController extends Controller {
 5     public function indexAction(){
 6         /*
 7         2016-3-23
 8         用以下兩種形式均可以訪問,加不加index.php均可以訪問
 9         http://localhost:81/research/thinkphp_3.2.3_full/home/user/index
10         http://localhost:81/research/thinkphp_3.2.3_full/index.php/home/user/index
11         */
12         //Home\Controller\UserController::index this is news controller Home\Controller\UserController
13         $str = 'inner ' . __METHOD__ . ' this is news controller ' . __CLASS__;
14         echo $str;
15     }
16 
17     public function getUser() {
18         return 'inner ' . __METHOD__ . ' zhangsan';
19     }
20 }
21 ?>

 

Application/Home/Controller/TestController.class.php

 1 <?php
 2 namespace Home\Controller;
 3 use Think\Controller;
 4 class TestController extends Controller {
 5     public function helloAction(){
 6         echo __METHOD__ . ' hello';
 7     }
 8 
 9     public function testAction(){
10         echo __METHOD__ . ' test';
11     }
12 
13     public function instanceConAction() {
14         //下面這兩種方式均可以實現化
15         //$user = new \Home\Controller\UserController();
16         $user = A('User');
17         echo 'inner ' . __METHOD__ . ' the name is ' . $user->getUser();
18     }
19 }
20 ?>

 

系統為上面的控制器實例化提供了一個快捷調用方法A,$user = new \Home\Controller\UserController();可以簡化為$user = A('User');

訪問:http://localhost:81/research/thinkphp_3.2.3_full/Home/Test/instanceCon
輸出:inner Home\Controller\TestController::instanceConAction the name is inner Home\Controller\UserController::getUser zhangsan


五、Action參數綁定

參數綁定是通過直接綁定URL地址中的變量作為操作方法的參數,可以簡化方法的定義甚至路由的解析。
參數綁定功能默認是開啟的,其原理是把URL中的參數(不包括模塊、控制器和操作名)和操作方法中的參數進行綁定。


1.按變量名綁定
要啟用參數綁定功能,首先確保你開啟了URL_PARAMS_BIND設置:
'URL_PARAMS_BIND' => true, // URL變量綁定到操作方法作為參數

訪問:http://localhost:81/research/thinkphp_3.2.3_full/Home/Blog/read/id/5
輸出:id=5

訪問http://localhost:81/research/thinkphp_3.2.3_full/Home/Blog/archive/year/2016/month/03
輸出year=2016&month=03

按照變量名進行參數綁定的參數必須和URL中傳入的變量名稱一致,但是參數順序不需要一致。也就是說
訪問:http://localhost:81/research/thinkphp_3.2.3_full/Home/Blog/archive/month/03/year/2016(輸出year=2016&month=03)
和上面的訪問結果是一致的,URL中的參數順序和操作方法中的參數順序都可以隨意調整,關鍵是確保參數名稱一致即可

下面的內容是ThinkPHP/conf/convention.php中的配置
'VAR_PATHINFO' => 's', // 兼容模式PATHINFO獲取變量例如 ?s=/module/action/id/1 后面的參數取決於URL_PATHINFO_DEPR


'URL_PATHINFO_DEPR' => '/', // PATHINFO模式下,各參數之間的分割符號

如果使用下面的URL地址進行訪問,參數綁定仍然有效:
http://localhost:81/research/thinkphp_3.2.3_full/index.php?s=/Home/Blog/read/id/5
http://localhost:81/research/thinkphp_3.2.3_full/index.php?s=/Home/Blog/archive/year/2013/month/11
http://localhost:81/research/thinkphp_3.2.3_full/index.php?c=Blog&a=read&id=5
http://localhost:81/research/thinkphp_3.2.3_full/index.php?c=Blog&a=archive&year=2013&month=11

 

Application/Home/Controller/BlogController.class.php

 1 <?php
 2 namespace Home\Controller;
 3 use Think\Controller;
 4 class BlogController extends Controller{
 5     public function read($id = 3){
 6         echo 'id='.$id;
 7     }
 8 
 9     public function archive($year='2013', $month='01'){
10         echo 'year='.$year.'&month='.$month;
11     }
12 
13     /**
14      * http://localhost:81/research/thinkphp_3.2.3_full/Home/Blog/input/year/2016/month/03
15      * path.1:input path.2:year path.3:2016
16      */
17     public function input() {
18         echo 'path.0: ' . I('path.0') . ' path.1: ' . I('path.1') . ' path.2: ' . I('path.2') . ' path.3: ' . I('path.3');
19         echo "\n";
20         echo 'get.year:' . I('get.year') . ' get.month:' . I('get.month');
21         echo "\n";
22 
23         print_r($_GET);
24     }
25 }
26 ?>

 

2.按變量順序綁定
第二種方式是按照變量的順序綁定,這種情況下URL地址中的參數順序非常重要,不能隨意調整。要按照變量順序進行綁定,必須先設置URL_PARAMS_BIND_TYPE為1:
'URL_PARAMS_BIND_TYPE' => 1, // 設置參數綁定按照變量順序綁定

將'URL_PARAMS_BIND_TYPE' => 1,加入到文件Application/Home/Conf/config.php中

訪問:http://localhost:81/research/thinkphp_3.2.3_full/Home/Blog/read/5
輸出: id=5

訪問:http://localhost:81/research/thinkphp_3.2.3_full/Home/Blog/archive/2016/03
輸出:year=2016&month=03

當設置URL_PARAMS_BIND_TYPE為1時,如果url中傳遞的參數仍然是按照變量名綁定,則輸出的結果不是我們想要的數據
訪問:http://localhost:81/research/thinkphp_3.2.3_full/Home/Blog/read/id/5
輸出: id=id

訪問:http://localhost:81/research/thinkphp_3.2.3_full/Home/Blog/archive/year/2016/month/03
輸出:year=year&month=2016

按變量順序綁定的方式目前僅對PATHINFO地址有效,所以下面的URL訪問參數綁定會失效:
http://localhost:81/research/thinkphp_3.2.3_full/index.php?c=Blog&a=read&id=5
http://localhost:81/research/thinkphp_3.2.3_full/index.php?c=Blog&a=archive&year=2013&month=11

但是,兼容模式URL地址訪問依然有效:
http://localhost:81/research/thinkphp_3.2.3_full/index.php?s=/Home/Blog/read/5
http://localhost:81/research/thinkphp_3.2.3_full/index.php?s=/Home/Blog/archive/2013/11


六、輸入變量

雖然你仍然可以在開發過程中使用傳統方式獲取各種系統變量,例如:
$id = $_GET['id']; // 獲取get變量
$name = $_POST['name']; // 獲取post變量
$value = $_SESSION['var']; // 獲取session變量
$name = $_COOKIE['name']; // 獲取cookie變量
$file = $_SERVER['PHP_SELF']; // 獲取server變量
但是我們不建議直接使用傳統方式獲取,因為沒有統一的安全處理機制,后期如果調整的話,改起來會比較麻煩。所以,更好的方式是在框架中統一使用I函數進行變量獲取和過濾。

path類型變量可以用於獲取URL參數(必須是PATHINFO模式參數有效,無論是GET還是POST方式都有效)

Application/Home/Controller/BlogController.class.php

 1 <?php
 2 namespace Home\Controller;
 3 use Think\Controller;
 4 class BlogController extends Controller{
 5     public function read($id = 3){
 6         echo 'id='.$id;
 7     }
 8 
 9     public function archive($year='2013', $month='01'){
10         echo 'year='.$year.'&month='.$month;
11     }
12 
13     /**
14      * http://localhost:81/research/thinkphp_3.2.3_full/Home/Blog/input/year/2016/month/03
15      * path.1:input path.2:year path.3:2016
16      */
17     public function input() {
18         echo 'path.0: ' . I('path.0') . ' path.1: ' . I('path.1') . ' path.2: ' . I('path.2') . ' path.3: ' . I('path.3');
19         echo "\n";
20         echo 'get.year:' . I('get.year') . ' get.month:' . I('get.month');
21         echo "\n";
22 
23         print_r($_GET);
24     }
25 }
26 ?>


訪問:http://localhost:81/research/thinkphp_3.2.3_full/index.php?m=Home&c=Blog&a=input&year=2016&month=03
輸出:
path.0: path.1: path.2: path.3:
get.year:2016 get.month:03
Array
(
[year] => 2016
[month] => 03
)


訪問:http://localhost:81/research/thinkphp_3.2.3_full/Home/Blog/input/2016/03
輸出:
path.0: Blog path.1: input path.2: 2016 path.3: 03
get.year: get.month:
Array
(
[0] => 2016
[1] => 03
)


七、空操作
空操作是指系統在找不到請求的操作方法的時候,會定位到空操作(_empty)方法來執行,利用這個機制,我們可以實現錯誤頁面和一些URL的優化。

Application/Home/Controller/CityController.class.php

 1 <?php
 2 namespace Home\Controller;
 3 use Think\Controller;
 4 class CityController extends Controller{
 5     public function _empty($name){
 6         //把所有城市的操作解析到city方法
 7         $this->city($name);
 8     }
 9 
10     //注意 city方法 本身是 protected 方法
11     protected function city($name){
12         //和$name這個城市相關的處理
13          echo '當前城市' . $name;
14     }
15 }
16 ?>


接下來,我們就可以在瀏覽器里面輸入
http://localhost:81/research/thinkphp_3.2.3_full/Home/City/beijing/
http://localhost:81/research/thinkphp_3.2.3_full/Home/City/shanghai/
http://localhost:81/research/thinkphp_3.2.3_full/Home/City/shenzhen/

由於City控制器並沒有定義beijing、shanghai或者shenzhen操作方法,因此系統會定位到空操作方法 _empty中去解析,_empty方法的參數就是當前URL里面的操作名,因此會看到依次輸出的結果是:
當前城市:beijing
當前城市:shanghai
當前城市:shenzhen


八、空控制器
空控制器的概念是指當系統找不到請求的控制器名稱的時候,系統會嘗試定位空控制器(EmptyController),利用這個機制我們可以用來定制錯誤頁面和進行URL的優化。

Application/Home/Controller/EmptyController.class.php

 1 <?php
 2 namespace Home\Controller;
 3 use Think\Controller;
 4 class EmptyController extends Controller{
 5     public function index(){
 6         //根據當前控制器名來判斷要執行那個城市的操作
 7         $cityName = CONTROLLER_NAME;
 8         /*
 9         訪問:http://localhost:81/research/thinkphp_3.2.3_full/Home/beijing/
10         CONTROLLER_NAME的值為Beijing
11         */
12         //echo 'CONTROLLER_NAME:' . CONTROLLER_NAME;
13         $this->city($cityName);
14     }
15 
16     //注意 city方法 本身是 protected 方法
17     protected function city($name){
18         //和$name這個城市相關的處理
19          echo '當前城市' . $name;
20     }
21 }
22 ?>

 

接下來,我們就可以在瀏覽器里面輸入
http://localhost:81/research/thinkphp_3.2.3_full/Home/beijing/
http://localhost:81/research/thinkphp_3.2.3_full/Home/shanghai/
http://localhost:81/research/thinkphp_3.2.3_full/Home/shenzhen/

由於系統並不存在beijing、shanghai或者shenzhen控制器,因此會定位到空控制器(EmptyController)去執行,會看到依次輸出的結果是:

當前城市:beijing
當前城市:shanghai
當前城市:shenzhen


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM