[TOC]
> 以下示例代碼我們都假設模塊為`index`,控制器為`IndexCtrl.php`,并且模塊沒有綁定域名,服務器支持rewrite,域名為`domain.com`。
### 定義控制器
* Lying的控制器都是放在模塊下的`controller`目錄。
* Lying的控制器必須繼承控制器基類`lying\base\Controller`。
* 控制器的命名是首字母大寫的駝峰命名+`Ctrl`,如:`PostListCtrl.php`,類名應和文件名一致。
* 如果要創建不可訪問的控制器,則去掉`Ctrl`即可,如:`PostList.php`。
* 控制器的命名空間是從`module`開始的`module\模塊名\controller`。
~~~php
<?php
namespace module\index\controller;
use lying\base\Controller;
class IndexCtrl extends Controller
{
}
~~~
這樣一個最基本的控制器就定義好了。
### 控制器方法
url訪問的時候其實就是訪問控制器的一個方法。我們這邊舉個栗子,定義一個`index`方法:
~~~php
<?php
namespace module\index\controller;
use lying\base\Controller;
class IndexCtrl extends Controller
{
public function index()
{
return '我訪問了' . __METHOD__;
}
}
~~~
現在我們訪問`domain.com/index/index/index`,是不是看到瀏覽器輸出了`'我訪問了index'`。方法里面`return`等同于`echo`,推薦用`return`,因為 [response](response.md) 類會對你所輸出的值進行處理
### 帶參數方法
你可以為你的控制器設置參數,參數可以設置默認值,如果不設置默認值,就必須在url中帶上該參數,參數名和變量名一致:
~~~php
<?php
namespace module\index\controller;
use lying\base\Controller;
class IndexCtrl extends Controller
{
public function index($id, $name = 'lying')
{
}
}
~~~
現在你可以這樣訪問:
~~~html
http://domain.com/index/index/index/id/3/name/yourname/
http://domain.com/index/index/index/id/3/
~~~
但是如果你這樣訪問的話,是要報錯的:
~~~html
http://domain.com/index/index/index/
http://domain.com/index/index/index/name/yourname/
~~~
因為你缺少了必須的參數`id`
* * * * *
當然,你還可以如下操作:
~~~php
<?php
namespace module\index\controller;
use lying\base\Controller;
class IndexCtrl extends Controller
{
public function index($id = 1, $name)
{
}
}
~~~
現在你可以這樣訪問:
~~~html
http://domain.com/index/index/index/id/3/name/yourname/
http://domain.com/index/index/index/name/yourname/
~~~
但是如果你這樣訪問的話,是要報錯的:
~~~html
http://domain.com/index/index/index/
http://domain.com/index/index/index/id/3/
~~~
因為你缺少了必須的參數`name`
> 你可以品味一下上述兩種定義的區別
### 初始化方法
* 你不能定義控制器的構造函數,因為控制器基類繼承服務類,服務類的構造函數定義為`final`的,因為要執行特定功能。
* 你可以重寫父類的`init`方法,這個方法類似構造函數執行,你可以把初始化代碼寫在這里:
~~~php
<?php
namespace module\index\controller;
use lying\base\Controller;
class IndexCtrl extends Controller
{
public function init()
{
parent::init();
//你的邏輯
}
}
~~~
> 請注意:如果重寫`init`方法,請在方法首行調用`parent::init();`。
* 你還可以定義`beforeAction`方法(前置操作)和`afterAction`(后置操作)方法:
~~~php
<?php
namespace module\index\controller;
use lying\base\Controller;
class IndexCtrl extends Controller
{
//這個方法將在你要執行的方法之前執行
public function beforeAction($event)
{
//記得在這個方法的首行調用父級的beforeAction
parent::beforeAction($event);
//獲取即將調用方法的ID
$action = $event->action;
//如果事件的return被設置為true,那么就不會再執行后面的方法和后置操作了
$event->return =true;
}
//這個方法將在你要執行的方法之后執行
public function afterAction($event)
{
//記得在這個方法的首行調用父級的afterAction
parent::afterAction($event);
//獲取已經調用方法的ID
$action = $event->action;
//獲取即將調用方法的返回值
$action = $event->response;
}
}
~~~
### 方法過濾器
你看了上面的特定方法,如果擔心用戶會執行到你的`init`方法,或者`beforeAction`、`afterAction`方法,這個你完全不必擔心,Lying為你提供了方法過濾器:
~~~php
<?php
namespace module\index\controller;
use lying\base\Controller;
class IndexCtrl extends Controller
{
public $deny = [ //接受一個正則數組對方法名進行過濾
'/^user/',
'/^before/'
];
}
~~~
如上定義的屬性`$deny`就是設定`user`和`before`開頭的方法都不允許訪問,拋出404錯誤。
> * 注意:控制器屬性`$deny`必須設置為`public`。
> * `init`、`beforeAction`、`afterAction`三個方法已經默認被過濾了。
### CSRF
Lying默認在控制器的基類的`beforeAction`校驗了CSRF的TOKEN值,如果你不喜歡,你可以重寫`beforeAction`函數,如果你重寫了`beforeAction`并且不需要默認的校驗,你可以:
~~~php
<?php
namespace module\index\controller;
use lying\base\Controller;
class IndexCtrl extends Controller
{
public function beforeAction($event) {
//parent::beforeAction($event); //注釋掉此行則不會進行CSRF校驗
//此處寫你的邏輯代碼
}
}
~~~
### 控制器快捷操作
~~~php
<?php
namespace module\index\controller;
use lying\base\Controller;
class IndexCtrl extends Controller
{
public function index()
{
$module = $this->module; //當前控制器所屬的模塊ID
$id = $this->id; //當前控制器所屬的控制器ID
$action = $this->action; //當前控制器執行的方法ID
$this->assign('username', 'Lying'); //渲染參數到模板,更多使用方式請參考視圖章節
return $this->render(); //渲染模板:當前模塊/view/控制器ID/index.php,更多使用方式請參考視圖章節
}
}
~~~
### 在控制器中獲取外部輸入
參見 [Request組件](request.md)
- 序言
- 更新日志
- 安裝
- 規范
- 常量
- 配置
- 自動加載
- MVC
- 模塊
- 控制器
- 模型
- 視圖
- php原生模板
- 模板引擎
- 變量輸出
- 模板注釋
- 模板繼承
- 模板引用
- 流程控制
- 原樣輸出
- 服務組件
- Hook組件
- Request組件
- Router組件
- Cookie組件
- Encrypter組件
- Dispatch組件
- Response組件
- View組件
- Session組件
- Helper組件
- 數據分頁
- 數據驗證
- Logger組件
- Cache組件
- Redis組件
- Connection組件
- 執行sql語句
- 查詢生成器
- 查詢方法詳解
- Schema
- Captcha組件
- CLI
- CLI工具
- 事件
- 類事件
- 實例事件
- 全局事件
- 助手函數
- 擴展
- 異常
- 部署
- Apache
- Nginx
- IIS
- 虛擬主機