Yii2 分析運行流程

 

http://blog.csdn.net/alex_my/article/details/54142711php

版本web

建立Applicationbootstrap

run過程app

handleRequestyii

runAction函數

簡述流程網站

1 版本this

 

// yii\BaseYii\getVersion
public static function getVersion()
{
    return '2.0.10';
}

2url

// web/index.php

new yii\web\Application($config)

// yii\base\Application.php

public function __construct($config = [])
{
    Yii::$app = $this;
    static::setInstance($this);

    $this->state = self::STATE_BEGIN;
    // 配置屬性
    $this->preInit($config);
    // 註冊error相關處理函數
    $this->registerErrorHandler($config);
    // 在基類的構造函數中將會調用init()函數
    // 在init()中直接調用bootstrap()函數
    // 先調用 web/Application::bootstrap()
    // 再調用 base/Application::bootstrap()
    Component::__construct($config);
}
//  base/Application::bootstrap()

protected function bootstrap()
{
    // 加載擴展清單中的文件, 默認使用 vendor/yiisoft/extensions.php
    if ($this->extensions === null) 
    {
        $file = Yii::getAlias('@vendor/yiisoft/extensions.php');
        $this->extensions = is_file($file) ? include($file) : [];
    }
    // 建立這些擴展組件
    // 若是這些組件實現了BootstrapInterface, 還會調用組件下的bootstrap函數
    foreach ($this->extensions as $extension)
    {
        if (!empty($extension['alias'])) 
        {
            foreach ($extension['alias'] as $name => $path) 
            {
                Yii::setAlias($name, $path);
            }
        }
        if (isset($extension['bootstrap'])) 
        {
            $component = Yii::createObject($extension['bootstrap']);
            if ($component instanceof BootstrapInterface)
            {
                Yii::trace('Bootstrap with ' . get_class($component) . '::bootstrap()', __METHOD__);
                $component->bootstrap($this);
            } 
            else 
            {
                Yii::trace('Bootstrap with ' . get_class($component), __METHOD__);
            }
        }
    }

    // 加載將要運行的一些組件, 這些組件配置在main.php, main-local.php中
    // 'bootstrap' => ['log'],
    // $config['bootstrap'][] = 'debug';
    // $config['bootstrap'][] = 'gii';
    // 開發模式下,默認加載3個: log, debug, gii
    // 從$config中的配置信息變成base\Application中的屬性$bootstrap經歷如下步驟:
    // Component::__construct  --> Yii::configure($this, $config)

    foreach ($this->bootstrap as $class) 
    {
        $component = null;
        if (is_string($class)) 
        {
            if ($this->has($class)) 
            {
                $component = $this->get($class);
            } 
            elseif ($this->hasModule($class))
            {
                $component = $this->getModule($class);
            } 
            elseif (strpos($class, '\\') === false) 
            {
                throw new InvalidConfigException("Unknown bootstrapping component ID: $class");
            }
        }
        if (!isset($component)) 
        {
            $component = Yii::createObject($class);
        }
        // 若是這些組件實現了BootstrapInterface, 還會調用組件下的bootstrap函數
        if ($component instanceof BootstrapInterface) 
        {
            Yii::trace('Bootstrap with ' . get_class($component) . '::bootstrap()', __METHOD__);
            $component->bootstrap($this);
        } 
        else 
        {
            Yii::trace('Bootstrap with ' . get_class($component), __METHOD__);
        }
    }
}

3 run過程

整個run過程經歷如下過程:spa

public function run()
{
    try {
        // 處理請求前
        $this->state = self::STATE_BEFORE_REQUEST;
        $this->trigger(self::EVENT_BEFORE_REQUEST);
        // 處理請求
        $this->state = self::STATE_HANDLING_REQUEST;
        $response = $this->handleRequest($this->getRequest());
        // 處理請求前
        $this->state = self::STATE_AFTER_REQUEST;
        $this->trigger(self::EVENT_AFTER_REQUEST);
        // 發送相應給客戶端
        $this->state = self::STATE_SENDING_RESPONSE;
        $response->send();
        $this->state = self::STATE_END;
        return $response->exitStatus;
    } catch (ExitException $e) {
        $this->end($e->statusCode, isset($response) ? $response : null);
        return $e->statusCode;
    }
}

4 handleRequest

public function handleRequest($request)
{
    // 若是設置了catchAll變量, 那麼全部請求都會跳轉到這裏
    // 示例:
    // 假設網站維護, 不但願有人訪問到內容
    // 能夠建立一個OfflineController控制器, 對應的views/offline/index.php能夠寫上
    // <h1>網站正在維護中</h1>
    // 而後在main.php中的$config中添加如下內容
    // 'catchAll' => [ 'offline/index']
    // 這樣, 全部的訪問都跳轉到 網站正在維護中 的頁面了

    if (empty($this->catchAll)) 
    {
        try 
        {
            list ($route, $params) = $request->resolve();
        } 
        catch (UrlNormalizerRedirectException $e) 
        {
            $url = $e->url;
            if (is_array($url)) 
            {
                if (isset($url[0])) 
                {
                    // ensure the route is absolute
                    $url[0] = '/' . ltrim($url[0], '/');
                }
                $url += $request->getQueryParams();
            }
            return $this->getResponse()->redirect(Url::to($url, $e->scheme), $e->statusCode);
        }
    } 
    // 跳轉到catchAll指定的route
    else 
    {
        $route = $this->catchAll[0];
        $params = $this->catchAll;
        unset($params[0]);
    }
    try 
    {
        Yii::trace("Route requested: '$route'", __METHOD__);
        $this->requestedRoute = $route;
        $result = $this->runAction($route, $params);
        ...
    }
    ...
}

5 runAction

建立Controller,並執行Controller對應的action

public function runAction($route, $params = [])
{
    // 建立Controller
    $parts = $this->createController($route);
    if (is_array($parts)) 
    {
        list($controller, $actionID) = $parts;
        $oldController = Yii::$app->controller;
        Yii::$app->controller = $controller;

        // 執行controller中的action
        $result = $controller->runAction($actionID, $params);
        if ($oldController !== null) 
        {
            Yii::$app->controller = $oldController;
        }
        return $result;
    } 
    else 
    {
        $id = $this->getUniqueId();
        throw new InvalidRouteException('Unable to resolve the request "' . ($id === '' ? $route : $id . '/' . $route) . '".');
    }
}
6 簡述流程

經過Application建立app, 而且讀入config, 裝載擴展和組件
經過request解析被請求的路由
app根據路由建立controller
controller建立action
若是過濾器經過, 則會執行action
action會渲染視圖view
view中的內容通常來自於model
渲染的結果經過response返回給客戶端
相關文章
相關標籤/搜索