Phalcon7 控制器的使用

2018-11-14 14:25 更新

控制器提供了一堆可以被調(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
Actionshow
參數(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)度

循環(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í)行。

注入服務(wù)

如果控制器繼承于 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ù)。

請求與響應(yīng)

假設(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 。

會話數(shù)據(jù)

會話可以幫助我們在多個(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ù)可以是控制器,控制器類通常會從服務(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;
});

創(chuàng)建基控制器

對于某些應(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í)行
    }
}
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號