控制器是 MVC 中的 ‘C’ 。在應用了路由且正確的控制器被找到之后,控制器的動作(action)被調用。控制器將處理解釋請求數據,確保正確的模型被調用,確保正確的輸出或視圖被渲染。控制器可被視為模型和視圖的中間人。你要保持控制器很精煉,而模型類很豐滿。這會幫助你更容易地重用你的代碼,并使你的代碼更易于測試。
通常,控制器用于管理單個視圖邏輯。例如,你為一個在線面包店建立站點,你可能會有一個 RecipesController 和一個 IngredientsController,管理你的食譜和原料。在 CakePHP 中,控制器用它們處理的主要模型命名。也常常會有一個控制器和多個模型共同工作的情況。
應用程序控制器擴展自 AppController 類,它擴展自內核的 Controller 類。AppController 類可以在/app/Controller/AppController.php 中定義,它可以包含應用程序中多個控制器共享的方法。
控制器提供的一些方法被叫做 動作(actions)。動作是控制器用來處理請求的方法。默認情況下,控制器中所有的公有方法都可以從 url 訪問。控制器負責解析請求并創建響應。通常響應是以渲染視圖的格式完成,但有時也會用其它途徑創建響應。
誠如介紹中所言,AppController 類是所有應用程序控制器的你類。 AppController 自身是擴展自 CakePHP 核心庫中的 Controller 類。 /app/Controller/AppController.php 文件中的 AppController 類類似于:
AppController 中建立的屬性和方法在應用程序的所有控制器中都可用。 它是放置所有控制器的公用代碼的最佳位置。 組件(你將會有后面學到)則用于存放許多控制器(但不一定是全部)都使用的代碼。
相對于正常的面向對象繼承規則,CakePHP 對于控制器的特殊屬性,做了一些擴展工作。組件和助手清單被控制器特殊對待。 在這些情況下,AppContrller 值數組和子控制器類的數組合并。子類的那些值總是覆蓋 AppController 類的同名值。
注解
CakePHP 合并 AppController 和你的應用程序控制器的如下變量:
如果你在 AppController 中定義了 $helpers ,記得添加默認的 Html 和 Form 助手。
還要記得在子類的回調方法中調用 AppController 的回調方法。
請求參數
在為 CakePHP 應用程序生成了請求之后,CakePHP 的 Router 和 Dispatcher 類使用 路由配置 尋找和建立正確的控制器。請求數據壓入一個請求對象。CakePHP 把所有重要的請求信息都放入 $this->request 屬性。關于 CakePHp 請求對象的更多信息請參看 CakeRequest 。
控制器負責將請求參數轉換成瀏覽器/用戶要求的響應。CakePHP 使用約定自動完成這些處理過程并移動了在其它情況下你需要編寫的一些程式化的代碼。
根據約定,CakePHP 渲染一個動作名映射的視圖。回到我們的在線面包店的例子,我們的 RecipesController 可能會包含 view()、share() 和 search() 動作。這個控制器在 /app/Controller/RecipesController.php 文件中,并且包含如下內容:
這些動作對應的視圖文件分別是 app/View/Recipes/view.ctp、 app/View/Recipes/share.ctp 和 andapp/View/Recipes/search.ctp。視圖文件名被規定為使用小寫和下劃線間隔的版本的動作名。
控制器動作通常使用 set() 來創建用于渲染視圖瓣 View 上下文。 由于使用 CakePHP 的約定,你不需要手動創建和渲染視圖。取而代之的是,一旦一個應用程序的動作完成,CakePHP 將處理視圖渲染和傳輸。
某些情況下你可能需要跳過默認的的行為。下面的技巧可以跳過默認的視圖渲染。
控制器方法使用 requestAction() 處理你想返回的非字符串數據。如果你的控制器方法使用 常規請求 + requestAction,你需要在運行前檢查請求的類型:
上面的控制器動作是如何在一個方法中使用 requestAction() 和常規請求。給非 requestActin 請求返回一個數組將引起錯誤,這是需要的避免的。關于使用 requestAction() 的更多提示請參閱 Controller::requestAction() 環節。
為使你在應用程序中更有效地使用控制器,我們提供了 CakePHP 控制器常用的一些核心屬性和方法。
CakePHP 控制器提供了能用來在請求生命周期中插入邏輯的回調:
這個函數在控制器中的每個動作前執行。 它是檢驗活動會話或用戶授權驗證的好地方。
注解
beforeFilter() 方法在找不到動作時或者腳手架動作執行前,也會執行。
在控制器動作邏輯之后、視圖渲染前調用。這個回調不常用,但是如果你在動作結束前手動調用 render() 時可能會需要它。
在控制器動作邏輯和渲染完成之后調用。這是運行時執行的最后一個控制器方法。
除了控制器周期回調之外,組件 也提供一組回調集。
完整的控制器方法列表及其描述請訪問 CakePHP API,瀏覽 http://api20.cakephp.org/class/controller。
控制器與視圖交互有幾種方法。 首先,可以使用 set() 向視圖傳送數據。還可以決定使用哪個視圖類,以及在控制器中渲染哪個視圖文件。
set() 方法是從控制器向視圖傳送數據的主要途徑。一旦你使用 set() ,就可以在視圖中訪問這些變量:
set() 方法還能將它的第一個參數設成一個關聯數組。這是在視圖中訪問信息集合時常用的方法。
在 1.3 版更改: 數組的鍵在被賦值到視圖前將不會被改變(例如,’underscored_key’ 不再會變成 ‘underscoredKey’):
屬性 $pageTitle 不存在,使用 set() 設置標題:
Controller::render(string $action, string $layout, string $file)
render() 在每個被請求的控制器動作結束前被自動調用。此方法執行所有的視圖邏輯(使用通過 set() 方法提供的數據),將視圖放進它的布局中,并且將其提供給最終用戶。
被渲染的默認視圖文件根據約定來決定。 如果 RecipesController 的 search() 動作被請求,此視圖文件 /app/View/Recipes/search.ctp 被渲染:
雖然 CakePHP 將在每個動作邏輯之后自動調用它(直到你將 $this->autoRender 設置為 false),但是你可以通過在控制器中使用 $action 指定另一個視圖文件。
如果 $action 以 ‘/’ 開頭,視圖文件或元素文件就以 /app/View 作為起始位置定位。這將允許元素渲染轉向,在 ajax 調用中非常有用。:
你還可以使用第三個參數 $file 指定另一個視圖或者元素文件。 $layout 參數允許你指定視圖在哪個布局中渲染。
在控制器中,你能夠渲染與約定不一樣的視圖。通過調用 render() 來實現這一目的。一旦你調用了 render(),CakePHP就不再試圖重新渲染默認的視圖了。