控制器提供了一堆可以被調(diào)用的方法,即:action。action是控制器中用于處理請求的方法。默認(rèn)情況下,全部 控制器public的方法都會映射到action并且可以通過URL訪問。action負(fù)責(zé)解釋請求和創(chuàng)建響應(yīng)。 通常,響應(yīng)是以渲染的視圖格式被創(chuàng)建,但也存在其他的方式來創(chuàng)建(譯者注:如AJAX請求返回JSON格式的數(shù)據(jù))。
例如,當(dāng)你訪問一個(gè)類似這樣的URL時(shí):http://localhost/blog/posts/show/2015/the-post-title,Phalcon默認(rèn)會這樣分解各個(gè)部分:
Phalcon目錄 | blog |
控制器 | posts |
Action | show |
參數(shù) | 2015 |
參數(shù) | the-post-title |
這時(shí),PostsController將會處理這個(gè)請求。在一個(gè)項(xiàng)目中,沒有強(qiáng)制指定放置控制器的地方,這些控制器都可以 通過使用 autoloaders 來加載,所以你可以根據(jù)需要自由組件你的控制器。
控制器類必須以“Controller”為后綴,action則須以“Action”為后綴。一個(gè)控制器類的例子如下:
<?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function showAction($year, $postTitle) { } }
額外的URI參數(shù)定義為action的參數(shù),以致這些參數(shù)可以簡單地通過本地變量來獲取??刂破?可以選擇繼承 Phalcon\Mvc\Controller 。如果繼承此基類,你的控制器類則能 輕松訪問應(yīng)用的各種服務(wù)。
沒有默認(rèn)缺省值的參數(shù)視為必須參數(shù)處理??梢韵馪HP那樣為參數(shù)設(shè)定一個(gè)默認(rèn)值:
<?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function showAction($year = 2015, $postTitle = 'some default title') { } }
參數(shù)將會按路由傳遞和函數(shù)定義一樣的順序來賦值。你可以使用以下根據(jù)參數(shù)名稱的方式來獲取任意一個(gè)參數(shù):
<?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function showAction() { $year = $this->dispatcher->getParam('year'); $postTitle = $this->dispatcher->getParam('postTitle'); } }
循環(huán)調(diào)度將會在分發(fā)器執(zhí)行,直到?jīng)]有action需要執(zhí)行為止。在上面的例子中,只有一個(gè)action 被執(zhí)行到?,F(xiàn)在讓我們來看下“forward”(轉(zhuǎn)發(fā))怎樣才能在循環(huán)調(diào)度里提供一個(gè)更加復(fù)雜的操作流,從而將執(zhí)行轉(zhuǎn)發(fā)到 另一個(gè)controller/action。
<?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function showAction($year, $postTitle) { $this->flash->error("You don't have permission to access this area"); // Forward flow to another action $this->dispatcher->forward( array( "controller" => "users", "action" => "signin" ) ); } }
如果用戶沒有訪問某個(gè)action的權(quán)限,那么請求將會被轉(zhuǎn)發(fā)到Users控制器的signin行為。
<?php use Phalcon\Mvc\Controller; class UsersController extends Controller { public function indexAction() { } public function signinAction() { } }
對于“forwards”轉(zhuǎn)發(fā)的次數(shù)沒有限制,只要不會形成循環(huán)重定向即可,否則就意味著 你的應(yīng)用將會停止(譯者注:如果瀏覽器發(fā)現(xiàn)一個(gè)請求循環(huán)重定向時(shí),會終止請求)。 如果在循環(huán)調(diào)度里面沒有其他action可以分發(fā),分發(fā)器將會自動(dòng)調(diào)用由 Phalcon\Mvc\View 管理的MVC的視圖層。
Phalcon\Mvc\Controller 提供了初始化的函數(shù),它會最先執(zhí)行,并優(yōu)于任何控制器 的其他action。不推薦使用“__construct”方法。
<?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public $settings; public function initialize() { $this->settings = array( "mySetting" => "value" ); } public function saveAction() { if ($this->settings["mySetting"] == "value") { // ... } } }
“initialize”僅僅會在事件“beforeExecuteRoute”成功執(zhí)行后才會被調(diào)用。這樣可以避免 在初始化中的應(yīng)用邏輯不會在未驗(yàn)證的情況下執(zhí)行不了。
如果你想在緊接著創(chuàng)建控制器對象的后面執(zhí)行一些初始化的邏輯,你要實(shí)現(xiàn)“onConstruct”方法:
<?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function onConstruct() { // ... } }
需要注意的是,即使待執(zhí)行的action在控制器不存在,或者用戶沒有 訪問到它(根據(jù)開發(fā)人員提供的自定義控制器接入),“onConstruct”都會被執(zhí)行。
如果控制器繼承于 Phalcon\Mvc\Controller ,那么它可以輕松訪問 應(yīng)用的服務(wù)容器。例如,如果我們類似這樣注冊了一個(gè)服務(wù):
<?php use Phalcon\Di; $di = new Di(); $di->set('storage', function () { return new Storage('/some/directory'); }, true);
那么,我們可以通常多種方式來訪問這個(gè)服務(wù):
<?php use Phalcon\Mvc\Controller; class FilesController extends Controller { public function saveAction() { // 以和服務(wù)相同名字的類屬性訪問 $this->storage->save('/some/file'); // 通過DI訪問服務(wù) $this->di->get('storage')->save('/some/file'); // 另一種方式:使用魔法getter來訪問 $this->di->getStorage()->save('/some/file'); // 另一種方式:使用魔法getter來訪問 $this->getDi()->getStorage()->save('/some/file'); // 使用數(shù)組下標(biāo) $this->di['storage']->save('/some/file'); } }
如果你是把Phalcon作為全能(Full-Stack)框架來使用,你可以閱讀框架中 by default 提供的服務(wù)。
假設(shè)框架預(yù)先提供了一系列的注冊的服務(wù)。我們這里將解釋如何和HTTP環(huán)境進(jìn)行關(guān)聯(lián)和交互。 “request”服務(wù)包含了一個(gè) Phalcon\Http\Request 的實(shí)例, “response”服務(wù)則包含了一個(gè) Phalcon\Http\Response 的實(shí)例,用來表示將要返回給客戶端的內(nèi)容。
<?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function saveAction() { // 檢查請求是否為POST if ($this->request->isPost() == true) { // 獲取POST數(shù)據(jù) $customerName = $this->request->getPost("name"); $customerBorn = $this->request->getPost("born"); } } }
響應(yīng)對象通常不會直接使用,但在action的執(zhí)行前會被創(chuàng)建,有時(shí)候 - 如在 一個(gè)afterDispatch事件中 - 它對于直接訪問響應(yīng)非常有幫助:
<?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function indexAction() { } public function notFoundAction() { // 發(fā)送一個(gè)HTTP 404 響應(yīng)的header $this->response->setStatusCode(404, "Not Found"); } }
如需學(xué)習(xí)了解HTTP環(huán)境更多內(nèi)容,請查看專題: request 和 response 。
會話可以幫助我們在多個(gè)請求中保持久化的數(shù)據(jù)。你可以從任何控制器中訪問 Phalcon\Session\Bag 以便封裝需要進(jìn)行持久化的數(shù)據(jù)。
<?php use Phalcon\Mvc\Controller; class UserController extends Controller { public function indexAction() { $this->persistent->name = "Michael"; } public function welcomeAction() { echo "Welcome, ", $this->persistent->name; } }
服務(wù)可以是控制器,控制器類通常會從服務(wù)容器中請求。據(jù)于此, 任何一個(gè)用其名字注冊的類都可以輕易地用一個(gè)控制器來替換:
<?php // 將一個(gè)控制器作為服務(wù)進(jìn)行注冊 $di->set('IndexController', function () { $component = new Component(); return $component; }); // 將一個(gè)命名空間下的控制器作為服務(wù)進(jìn)行注冊 $di->set('Backend\Controllers\IndexController', function () { $component = new Component(); return $component; });
對于某些應(yīng)用特性如訪問控制列表(ACL),翻譯,緩存,和模板引擎一般對于 控制器都是通用的。在這種情況下,我們鼓勵(lì)創(chuàng)建一個(gè) “基控制器”,從而確保你的代碼遵循 DRY 。 基控制器可以是一個(gè)簡單的類,然后繼承于 Phalcon\Mvc\Controller ,并封裝 全部控制器都有的通用功能操作。反過來,你的控制器則繼承這個(gè)“基控制器”以便可以直接使用通用功能操作。
這個(gè)基類可以放置在任何一個(gè)地方,但出于代碼組織的便利我們推薦應(yīng)該放置在控制器的目錄下, 如:apps/controllers/ControllerBase.php。我們可以在啟動(dòng)文件直接require這個(gè)文件,也可以使用自動(dòng)加載:
<?php require "../app/controllers/ControllerBase.php";
對通用組件(action,方法,和類屬性等)也在這個(gè)基類文件里面:
<?php use Phalcon\Mvc\Controller; class ControllerBase extends Controller { /** * 這個(gè)方法可以被不同的控制器子類使用 */ public function someAction() { } }
現(xiàn)在,其他全部的控制都繼承于ControllerBase,然后便可訪問通用組件(如上面講到的的):
<?php class UsersController extends ControllerBase { }
控制器會自動(dòng)作為 dispatcher 事件的偵聽者,使用這些事件并實(shí)現(xiàn)實(shí)現(xiàn)這些方法后, 你便可以實(shí)現(xiàn)對應(yīng)被執(zhí)行的action的before/after鉤子函數(shù):
<?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function beforeExecuteRoute($dispatcher) { // 這個(gè)方法會在每一個(gè)能找到的action前執(zhí)行 if ($dispatcher->getActionName() == 'save') { $this->flash->error("You don't have permission to save posts"); $this->dispatcher->forward( array( 'controller' => 'home', 'action' => 'index' ) ); return false; } } public function afterExecuteRoute($dispatcher) { // 在找到的action后執(zhí)行 } }
更多建議: