Yii的版本化

本文連接:https://www.cnblogs.com/alanabc/p/10246023.htmlhtml

講解思路

把關係提到前面來說,但願可以大體說清楚吧:web

  • 版本化須要路由支持,這樣才能從URL中解析並定位到方法;
  • 定位方法須要先定位到控制器;
  • 控制器有兩種:
    • 一種是默認的,經過controllerNamespace進行指定
    • 另外一種是組件裏的,經過組件的「加載」進行指定

Yii的版本化,說白了就是經過路由,把URL定位到對應的方法去。瀏覽器

咱們這裏用Yii的基礎版(basic)做爲講解模板吧。服務器

路由機制

路由機制的工做過程,簡單來講就是:yii2

  • 當客戶端(好比瀏覽器)發起請求時,先經過URL定位文件,而後把請求送達這個文件進行處理和響應。
  • 若沒法經過URL直接定位到文件,則經過index.php來接收請求(這裏可能須要配置一下你的web服務器)。app

  • index.php接收到請求後,先送達路由管理器,經過路由解析出URL對應的方法,而後送達這個方法,由方法受理請求並做出響應。框架

  • 當沒法定位到文件也沒法解析出方法時,通常來講作404錯誤處理,表示資源不存在。yii

如何定位

在框架中,除了靜態資源是直接定位文件,其餘的請求都是路由到某個方法進行處理。Yii是一個面向對象的框架,路由表經過命名空間來一步一步的解析class、action,肯定處理請求的方法。好比,在基礎版中,請求URL<域名>/index.php?r=site/index,定位到SiteControlleractionIndex方法。ide

那麼路由表是怎麼知道,URL裏的site指的就是SiteController呢?繼續看:

控制器命名空間 - controllerNamespace

Yii的配置文件裏,有一項很重要的配置是controllerNamespace,顧名思義就是控制器的命名空間。在基礎版裏,它大概是這麼配置的:'controllerNamespace' => 'app\controllers',根據這個命名空間,路由就能找到控制器的目錄,而後就能定位到控制器和方法了。固然,你看不到它,由於這是核心框架的默認配置。若是你想要驗證個人說法,那麼:

vendor\yiisoft\yii2\base\Application.php line 95

/**
 * @var string the namespace that controller classes are located in.
 * This namespace will be used to load controller classes by prepending it to the controller class name.
 * The default namespace is `app\controllers`.
 *
 * Please refer to the [guide about class autoloading](guide:concept-autoloading.md) for more details.
 */
public $controllerNamespace = 'app\\controllers';

當你請求URL<域名>?r=site/index時,路由會去尋找app\controllers\SiteController這個類(其實就是去應用根目錄下的controllers裏尋找SiteController.php文件),而後找到裏面的actionIndex方法。

憑什麼site就對應SiteController類,index就對應actionIndex方法?它也是默認的配置!不過那就是另外一件話題了。

模塊 - modules

你使用過Yii自帶的debug組件嗎?若是沒有,那你應該知道,當啓用了這個組件,你就有兩種方式能夠使用它:一是在頁面的右下角,會有一個Yii的小logo,展開它就是debug組件;二是經過<域名>/index.php?r=debug/default/index,直接打開debug頁面。

yii-debug組件必然是有處理請求的方法的,但是爲啥上面這個URL能夠準肯定位到方法呢,controllerNamespace裏沒有配置過它呀?

其實yii-debug是一個組件(module),每個組件都由控制器、模型、視圖等構成,是一個獨立的小應用。對於這樣的組件,咱們要在$config['modules']裏配置,而後就能掛載它,你就能夠正常使用了。也正是這個「掛載」的過程,框架尋找到了對應的命名空間,就能夠準確的找到控制器和方法了。

1547022485527.png

咱們來找找這個組件吧:vendor\yiisoft\yii2-debug,會找到文件Module.php

<?php
namespace yii\debug;
//use ...
class Module extends \yii\base\Module implements BootstrapInterface
{
    //...
}

它繼承了\yii\base\Module類,這是一個模塊類,你只須要知道,繼承模塊類的文件在對應的目錄時,會被自動加載。

模塊和版本化

組件的「掛載」大體就是這樣。但是這和版本化有什麼關係?關係可大了,咱們的版本化,就是依靠組件實現的。

先來梳理一下:

  • 版本化須要路由支持,這樣才能從URL中解析並定位到方法;
  • 定位方法須要先定位到控制器;
  • 控制器有兩種:
    • 一種是默認的,經過controllerNamespace進行指定
    • 另外一種是組件裏的,經過組件的「加載」進行指定

動手作

咱們在上面看到,yii-debug組件是在配置項的$config['modules']裏多加了一個debug組件,而且指明瞭'class' => 'yii\debug\Module'

仍然是拿Yii基礎版來,作個簡單的「版本化」:我如今打算增長一個version1應用,算是加了一個「版本1」吧。

編寫配置

首先在配置文件web.php裏:

$config = [
    //略...
    'modules' => [
        //這裏class指定的是模塊類,看下文
        'version1' => ['class' => 'app\version1\Version1'],
    ],
];

編寫模塊

上面配置裏的class可不是亂寫的哦!是有依據的。

在應用根目錄下新建文件夾version1vendor同一級,兄弟文件夾),在文件夾內新建文件Version1.php做爲一個模塊類,繼承\yii\base\Module。在這個類裏面還指定了$controllerNamespace,注意跟上文提到的不同:上文指定的是整個應用的,這裏指定的是組件本身的:

<?php
namespace app\version1;

class Version1 extends \yii\base\Module
{
    //這裏指定的是組件本身的控制器命名空間
    public $controllerNamespace = 'app\version1\controllers';

    public function init()
    {
        parent::init();
    }
}

接下來在version1文件夾裏繼續新建三個子文件夾:

  • controllers:控制器文件夾。裏面的控制器文件,命名空間要寫成namespace app\version1\controllers;
  • models:模型文件夾。裏面的模型文件,命名空間要寫成namespace app\version1\models;
  • views:視圖文件夾

你只要像正常的那樣在這三個文件夾裏寫你的代碼就能夠了。

編寫路由

最後,去配置一下路由:

'urlManager' => [
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [
        'version1/<controller:[\w-]+>/<action:[\w-]+>'
            => 'version1/<controller>/<action>', //version1路由
        '<controller:[\w-]+>/<action:[\w-]+>'
            => '<controller>/<action>', //原有應用的路由(好比本來URL:<域名>/index.php?r=site/index,如今URL:<域名>/site/index)
        //其餘略...
    ],
],

這樣,訪問URL<域名>/version1/site/index的時候,就路由到version1SiteControlleractionIndex方法進行處理。

結語

語言組織的不夠好見諒!

API的版本化和上面的也沒什麼太大的區別,你能夠試着把API作個版本化;還能夠試着把Yii基礎版配置成Yii高級版的樣子,這樣能夠加深理解。

相關文章
相關標籤/搜索