來!狂擼一款PHP現代化框架 (路由的設計)

clipboard.png

前言

上一篇的標題改了一下,以1、2、三爲章節對讀者來講是種困擾,如今的標題是依照項目進度來編寫的。上篇文章地址爲 https://segmentfault.com/a/11...php

這一系列文章並不許備寫太多章節,大概規劃的只有4~5章左右,具體實現代碼還請移步Github
https://github.com/CrazyCodes...git

本章詳細講解一下Route(路由的實現),Come on Up Imagegithub

clipboard.png

上圖大概說明了實現路由要通過兩個步驟segmentfault

  • 將全部路由信息存儲到超全局變量中
  • 用戶請求時從全局變量中查找路由映射的服務腳本並實例化

OK,大概流程就是醬紫,下面開始「擼」框架

目錄

路由的代碼暫分爲如下幾個文件(這並非肯定的,詳細可查看Github)post

文件名 註釋
Route 轉發文件:爲實現 Route::get 效果
RouteCollection 路由信息處理存儲
RouteInterface 無需解釋
RouteModel 路由模型,將每一個路由信息以結構體方式存儲到$_SERVER
Router 路由的核心類

莫急,咱們一個一個文件來看。先從RouteInterface開始測試

RouteInterface

參照RESTful規定設定接口方法分別爲 GET、POST、PATCH、PUT、DELETE、OPTIONS,固然Laravel也是規範了以上標準請求。this

GitHub : https://github.com/CrazyCodes...spa

interface RouteInterface
{
    /**
     * @param      $uri
     * @param null $action
     *
     * @return mixed
     */
    public function get($uri, $action = null);

    /**
     * @param      $uri
     * @param null $action
     *
     * @return mixed
     */
    public function post($uri, $action = null);

    /**
     * @param      $uri
     * @param null $action
     *
     * @return mixed
     */
    public function patch($uri, $action = null);

    /**
     * @param      $uri
     * @param null $action
     *
     * @return mixed
     */
    public function put($uri, $action = null);

    /**
     * @param      $uri
     * @param null $action
     *
     * @return mixed
     */
    public function delete($uri, $action = null);

    /**
     * @param      $uri
     * @param null $action
     *
     * @return mixed
     */
    public function options($uri, $action = null);
}

Router

先寫一個栗子設計

public function get($uri, $action = null)
{
    return $this->addRoute("GET", $uri, $action);
}

用戶調用下方代碼會指向上述方法,方法既調用addRoute方法將路由信息存儲到$_SERVER中

Route::get('/','Controller')

如下爲addRoute部分的代碼

public function addRoute($methods, $uri, $action)
{
    // 這裏判斷請求方式是否合規,既是否存在  GET、POST、PATCH、PUT、DELETE、OPTIONS其中之一
    if ($this->verify($methods) == false) {
        return false;
    }
    
    // 以後咱們去往RouteCollection路由信息的處理類中
    return $this->routes->add($uri, $this->createRoute($methods, $action));
}

RouteCollection

最終達到 add 方法,將路由信息存儲到$_SERVER中

public function add($uri, RouteModel $model)
{
    if (empty($_SERVER["routes"][$uri])) {
        $_SERVER["routes"][$uri] = $model;
    }
}

第二個參數RouteModel開始咱們說過這是路由模型,將每一個路由以結構體的方式存儲到變量中,存儲後的結果

'routes' =>
  array(6) {
    'test/get' =>
    class Zero\Routing\RouteModel#13 (2) {
      public $method =>
      string(3) "GET"
      public $action =>
      string(19) "testController@test"
    }
    'test/post' =>
    class Zero\Routing\RouteModel#14 (2) {
      public $method =>
      string(4) "POST"
      public $action =>
      string(19) "testController@test"
    }
    'test/put' =>
    class Zero\Routing\RouteModel#15 (2) {
      public $method =>
      string(3) "PUT"
      public $action =>
      string(18) "testController@put"
    }
    'test/del' =>
    class Zero\Routing\RouteModel#16 (2) {
      public $method =>
      string(6) "DELETE"
      public $action =>
      string(18) "testController@del"
    }
    'test/patch' =>
    class Zero\Routing\RouteModel#17 (2) {
      public $method =>
      string(5) "PATCH"
      public $action =>
      string(20) "testController@patch"
    }
    'test/opt' =>
    class Zero\Routing\RouteModel#18 (2) {
      public $method =>
      string(7) "OPTIONS"
      public $action =>
      string(18) "testController@opt"
    }
  }

Route

最後經過__callStatic將代碼重定向到核心類中

public static function __callStatic($name, $arguments)
{
    $router = new Router;
    
    return $router->{$name}($arguments[0], $arguments[1]);
}

上述套路部分是Laravel的設計思想,經過這款簡單的框架可對Laravel核心設計有丁點的理解。

測試

測試上次作的有點糙,從本章到系列結束,咱們都以PHPunit來測試。

/**
 * @content tests all methods storage -> $_SERVER["routes"]
 */
public function testAllMethodsStorage()
{
    $this->routes->get($methodGet = "test/get", "testController@test");
    $this->assertArrayHasKey($methodGet, $_SERVER[$this->methodsDataKey]);
    
    $this->routes->post($methodPost = "test/post", "testController@test");
    $this->assertArrayHasKey($methodPost, $_SERVER[$this->methodsDataKey]);
    
    $this->routes->put($methodPut = "test/put", "testController@put");
    $this->assertArrayHasKey($methodPut, $_SERVER[$this->methodsDataKey]);
    
    $this->routes->delete($methodDel = "test/del", "testController@del");
    $this->assertArrayHasKey($methodDel, $_SERVER[$this->methodsDataKey]);
    
    $this->routes->patch($methodPatch = "test/patch", "testController@patch");
    $this->assertArrayHasKey($methodPatch, $_SERVER[$this->methodsDataKey]);
    
    $this->routes->options($methodOpt = "test/opt", "testController@opt");
    $this->assertArrayHasKey($methodOpt, $_SERVER[$this->methodsDataKey]);
}

上述貼出部分代碼,以過程化的方法去測試。查看存儲是否符合預期。

/**
 * @content RouteModel Success
 */
public function testCreateRoute()
{
    $response = $this->routes->createRoute("GET", "TestController@Get");
    
    $this->assertInstanceOf(RouteModel::class, $response);
}

包括測試對路由建立後是否爲RouteModel的實現。具體可查看Github
https://github.com/CrazyCodes...

致謝

上述已完成了路由的基本設計,下一章將講解從啓動到請求路由映射到服務腳本的過程。

但願本章能夠幫到你,謝謝。

相關文章
相關標籤/搜索