GY的實驗室 - Phalcon的MVC框架解析(一)

MVC例子

官方文檔的例子phalcon-mvc
先從簡單的開始。php

1. mvc/simple

從最簡單的入手吧. 把一些能及時說明白的東西寫在註釋裏了,須要擴展的知識列在下面。html

public/index.phpgit

<?php
$loader = new \Phalcon\Loader(); //反斜槓看着不習慣?請參見下面的[ 名字空間 ]
// 註冊自動加載的類目錄,爲方便使用,在php解析程序啓動時直接加載,參見[ 類的預加載 ]
$loader->registerDirs(array('../apps/controllers/', '../apps/models/'));
// Loader也要註冊自身
$loader->register();
// 依賴注入器,參見[ 依賴注入 ],在深刻到概念中以前,能夠理解爲構造類對象的地方
$di = new \Phalcon\DI();
// 下面是一些必需的對象
// 路由器: 將URI地址解析成Controller\Action\Params的模塊
$di->set('router', 'Phalcon\Mvc\Router');
// 分發器: 利用Router解析獲得的信息找到函數並執行
$di->set('dispatcher', 'Phalcon\Mvc\Dispatcher');
// 響應模塊: 將執行結果封裝成http協議,併發送給瀏覽器
$di->set('response', 'Phalcon\Http\Response');
// 請求模塊: 將到來的http請求封裝成對象,在dispatcher發給controller時也會把對象帶過去便於訪問 
$di->set('request', 'Phalcon\Http\Request');
// 視圖: 注入視圖對象,當dispatcher調用時被訪問
$di->set('view', function(){
    $view = new \Phalcon\Mvc\View();
    $view->setViewsDir('../apps/views/');
    return $view;
});
// 數據庫對象
$di->set('db', function(){
    return new \Phalcon\Db\Adapter\Pdo\Mysql(array(
        "host" => "localhost",
        "username" => "root",
        "password" => "",
        "dbname" => "invo"
    ));
});
// 數據表的元數據 : Memory表示該對象用於臨時獲取表結構,對象析構後表結構數據清除
$di->set('modelsMetadata', 'Phalcon\Mvc\Model\Metadata\Memory');
// 管理着Model的初始化、對應關係的類
$di->set('modelsManager', 'Phalcon\Mvc\Model\Manager');
try {
    //太簡單了,一個Application類搞定主邏輯 [ 應用類 ]
    $application = new \Phalcon\Mvc\Application();
    $application->setDI($di);
    echo $application->handle()->getContent();
}
catch(Phalcon\Exception $e){
    echo $e->getMessage();
}

註解:github

名字空間:sql

php在5.3.0版本之後開始支持的特性,用於解決兩類問題 —— 命名衝突和給類重命名. 使用命名空間:別名/導入數據庫

類的預加載:瀏覽器

爲了在使用一些類時不用寫require或include,能夠在php啓動時就把一些目錄下的類加載進來閉包

依賴注入:併發

依賴注入是控制反轉模式的一種實現。徹底得解釋依賴注入很難作到,由於這個模式被不一樣語言,不一樣框架用到,實現也各不相同。針對於Phalcon,能夠看得出依賴注入(DI)模塊是個容器,將類的生成方法寫到DI容器中, 當有用到依賴時去DI中取出便可。具體DI的做用官方文檔寫得太好了官方文檔mvc

應用類:

封裝了一些經常使用注入的類。當有它在時你可能不知道它作了些什麼,除非看一下不用它咱們須要作什麼。見下面的例子simple-without-application

controllers/ProductsController.php

<?php
// 控制器是用來執行業務邏輯的模塊,每一個方法叫作一個動做
// URL美化後通常是這樣路由的:www.demo.com/controllername/actionname/params
class ProductsController extends \Phalcon\Mvc\Controller {
    // action執行的結果使用view渲染,傳遞變量給對應的view,對應規則靠路徑
    public function indexAction(){
        $this->view->setVar('product', Products::findFirst());
    }
}

官方文檔-使用controller

models/Products.php

<?php
// Phalcon的Model類是用來與數據庫打交道的,大多數狀況下,一個model對應一張表
// source表示表名,setSource設置,getSource獲取
// 默認表名是to_lower(ModelClassName)
class Products extends \Phalcon\Mvc\Model {
    // 與controller同樣,不建議用__construct,而是initialize
    public function initialize(){
        $this->setSource('products');
    }
}

2. mvc/simple-without-application

只看public/index.php就能夠了,其餘文件雷同

// 路由器執行handle()
$router = $di->getShared('router');
$router->handle();

// 調度器傳入路由器解析獲得的controller和action以及參數
$dispatcher = $di->getShared('dispatcher');
$dispatcher->setControllerName($router->getControllerName());
$dispatcher->setActionName($router->getActionName());
$dispatcher->setParams($router->getParams());

// 調度:調用對應的controller::action函數
$dispatcher->dispatch();

// 渲染視圖
$view = $di->getShared('view');
$view->start();
$view->render($dispatcher->getControllerName(), $dispatcher->getActionName(), $dispatcher->getParams());
$view->finish();

// 封裝返回報文併發送給客戶端
$response = $di->getShared('response');
$response->setContent($view->getContent());
$response->sendHeaders();
echo $response->getContent();

這些就是Application的工做,仍是有Application省事啊!

3. mvc/single與mvc/single-namespaces

這是兩個對比case,意在闡明自定義namespace的用法。從例2中咱們看到application負責路由調度和渲染,可是不負責DI注入。在single的例子中,自定義了application,把依賴注入的代碼封裝進去了,使得主邏輯只剩下很是少的代碼

class Application extends \Phalcon\Mvc\Application {
    protected function _registerAutoloaders() {
        $loader = new \Phalcon\Loader();
        $loader->registerDirs(array(
            '../apps/controllers/',
            '../apps/models/'
        ));
        $loader->register();
    }
    protected function _registerServices() {
        $di = new \Phalcon\DI();
        $di->set('router',...);
        $di->set('dispatcher',...);
        $di->set('response',...);
        $di->set('request',...);
        $di->set('view',...);
        $di->set('db',...);
        $di->set('modelsMetadata',..);
        $di->set('modelsManager',...);
        $this->setDI($di);
    }
    public function main() {
           $this->_registerServices();
        $this->_registerAutoloaders();
           echo $this->handle()->getContent();
    }
}

// 主邏輯
try {
    $application = new Application();
    $application->main();
}
catch(Phalcon\Exception $e){
    echo $e->getMessage();
}

上述代碼註冊controller和model的class,用的方式是registerDirs。
single-namespaces也一樣自動加載自定義的controller和model,用的方式是registerNamespaces。

$loader->registerNamespaces(array(
    'Single\Controllers' => '../apps/controllers/',
    'Single\Models' => '../apps/models/'
));

由於引入了命名空間,使用時也須要顯示聲明

namespace Single\Controllers;
use Single\Models\Products as Products;

namespace Single\Models;
class Products extends \Phalcon\Mvc\Model {
    ...
}

4. mvc/single-factory-default

引入了配置項。這裏用到了Include()的返回值,還用到了PHP 5.3之後才支持的閉包語法: function () use($config) {...}
參見 : 閉包語法詳解

相關文章
相關標籤/搜索