专栏首页Grace development来!狂撸一款PHP现代化框架 (路由的设计)

来!狂撸一款PHP现代化框架 (路由的设计)

前言

上一篇的标题改了一下,以一、二、三为章节对读者来说是种困扰,现在的标题是依照项目进度来编写的。上篇文章地址为 https://segmentfault.com/a/1190000017278828

这一系列文章并不准备写太多章节,大概规划的只有4~5章左右,具体实现代码还请移步Github https://github.com/CrazyCodes/z_framework

本章详细讲解一下Route(路由的实现),Come on Up Image

上图大概说明了实现路由要经过两个步骤 – 将所有路由信息存储到超全局变量中 – 用户请求时从全局变量中查找路由映射的服务脚本并实例化

OK,大概流程就是酱紫,下面开始“撸”

目录

路由的代码暂分为以下几个文件(这并不是确定的,详细可查看Github)

文件名

注释

Route

转发文件:为实现 Route::get 效果

RouteCollection

路由信息处理存储

RouteInterface

无需解释

RouteModel

路由模型,将每个路由信息以结构体方式存储到$_SERVER

Router

路由的核心类

莫急,我们一个一个文件来看。先从RouteInterface开始

RouteInterface

参照RESTful规定设定接口方法分别为 GET、POST、PATCH、PUT、DELETE、OPTIONS,当然Laravel也是规范了以上标准请求。

GitHub : https://github.com/CrazyCodes/z_framework/blob/master/src/Zero/ZeroInterface.php

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/z_framework/tree/master/tests/Routing

致谢

上述已完成了路由的基本设计,下一章将讲解从启动到请求路由映射到服务脚本的过程。

希望本章可以帮到你,谢谢。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Laravel源码解析之路由的使用

    我的解析文章并非深层次多领域的解析攻略。但是参考着开发文档看此类文章会让你在日常开发中更上一层楼。

    CrazyCodes
  • PHP反射类export方法详细解析

    CrazyCodes
  • Laravel源码解析之Model

    根据单一责任开发原则来讲,在laravel的开发过程中每个表都应建立一个model对外服务和调用。类似于这样

    CrazyCodes
  • SpringBoot与Web开发

    用户1112962
  • React Native与Android 原生通信

    我们用React Native 做混合开发的时候免不了要原生和React Native 进行通信交互,这篇文章就是分享原生模块与JS传递数据的几种方式。

    HelloJack
  • Spring注解式编程

    相比较XML配置来说,当项目过大的时候难以维护。Spring还有一种支持0配置的注解式编程。

    OPice
  • 动手实现AOP

    “ 在前面的两篇文章中,我们了解了Spring AOP的应用以及两种动态代理的实现,但是如何实现AOP我想小伙伴应该会很疑惑,所以今天我们自己来动手撸代码简单的...

    每天学Java
  • ThreadLocal解析与最佳实践

    用于同一个线程内的方法要共享某些变量或状态的时候,提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递...

    LNAmp
  • Java爬虫(3)——拼接url抓取“加载更多”内容

    上期我们说到phantomjs可模拟点击按钮行为,通过点击完所有”加载更多”按钮来抓所有内容。比如这个网页http://e.vnexpress.net/news...

    聚沙成塔
  • Netty 系列六(编解码器).

        网络传输的单位是字节,如何将应用程序的数据转换为字节,以及将字节转换为应用程序的数据,就要说到到我们该篇介绍的编码器和解码器。

    JMCui

扫码关注云+社区

领取腾讯云代金券