github地址:https://github.com/NoahBuscher/Macaw/blob/master/Macaw.php

代码加上一些注释,方便以后再看。

<?php namespace NoahBuscher\Macaw;

/**
* method static Macaw get(string $route, Callable $callback)
* method static Macaw post(string $route, Callable $callback)
* method static Macaw put(string $route, Callable $callback)
* method static Macaw delete(string $route, Callable $callback)
* method static Macaw options(string $route, Callable $callback)
* method static Macaw head(string $route, Callable $callback)
*/
class Macaw {
public static $halts = false;
public static $routes = array();
public static $methods = array();
public static $callbacks = array();
public static $patterns = array(
':any' => '[^/]+',
':num' => '[0-9]+',
':all' => '.*',
);
public static $error_callback;
/**
* Defines a route w/ callback and method
* 注册路由,把注册的方法(GET,POST..),uri,closure分别push到对应的数组中
*/
public static function __callstatic( $method, $params ) {
$uri = $params[0];
$callback = $params[1];
array_push( self::$routes, $uri );
array_push( self::$methods, strtoupper( $method ) );
array_push( self::$callbacks, $callback );
}
/**
* Defines callback if route is not found
* 可以自定义没找到路由时执行的方法
*/
public static function error( $callback ) {
self::$error_callback = $callback;
} /**
* 自定义是否匹配到一次就停止,true停止,false不停止即可以定义多个同名路由,通过foreach全部执行
* @param boolean $flag true / false
* @return none
*/
public static function haltOnMatch( $flag = true ) {
self::$halts = $flag;
}
/**
* Runs the callback for the given request
* 根据当前的uri匹配对应的路由并执行
*/
public static function dispatch() {
$uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ); //路径部分(包括前边的/),不包括参数
$method = $_SERVER['REQUEST_METHOD']; //方法 GET / POST / PUT / DELETE
$searchs = array_keys( static::$patterns );
$replaces = array_values( static::$patterns );
$found_route = false; //check if route is defined without regex,检查是否定义了路由(非:any,:all形式的)
if ( in_array( $uri, self::$routes ) ) {
$route_pos = array_keys( self::$routes, $uri ); //返回匹配路由的键值,可能多个(同名路由)
foreach ( $route_pos as $route ) {
if ( self::$methods[$route] == $method ) { //寻找路由对应的方法名(GET,POST...),确定是否注册。
$found_route = true;
//if route is not an object,检测对应闭包函数是function还是controller route
if ( !is_object( self::$callbacks[$route] ) ) {
//grab all parts based on a / separator 控制器路由
$parts = explode( '/', self::$callbacks[$route] );
//collect the last index of the array
$last = end( $parts );
//grab the controller name and method call
$segments = explode( '@', $last );
//instanitate controller
$controller = new $segments[0]();
//call method
$controller->$segments[1]();
if ( self::$halts )return; //匹配一次就停止? }else {
//call closure
call_user_func( self::$callbacks[$route] );
if ( self::$halts )return;
} } }
}else {
//check if defined with regex 是否注册了正则路由(:any,:num..)
$pos = 0;
foreach ( self::$routes as $route ) {
if ( strpos( $route, ':' ) !== false ) {
$route = str_replace( $searchs, $replaces, $route );
}
if ( preg_match( '#^'.$route.'$#', $uri, $matched ) ) {
if ( self::$methods[$pos] == $method ) {
$found_route = true;
array_shift( $matched );
if ( !is_object( self::$callbacks[$pos] ) ) {
//grab all parts based on a / separator
$parts = explode( '/', self::$callbacks[$pos] );
//collect the last index of the array
$last = end( $parts );
//grab the controller name and method call
$segments = explode( '@', $last );
//instanitate controller
$controller = new $segments[0]();
//call method and pass any extra parameters to the method
$controller->$segments[1]( implode( ",", $matched ) );
if ( self::$halts ) {
return;
}else {
call_user_func_array( self::$callbacks[$pos], $matched );
if ( self::$halts ) return;
} }
}
}
$pos++;
}
} //return the error callback if the route was not found
if ( $found_route == false ) {
if ( !self::$error_callback ) {
self::$error_callback = function() {
header( $_SERVER['SERVER_PROTOCOL']." 404 Not Found" ); //请求页面时通信协议的名称和版本。例如,“HTTP/1.0”。
echo '404';
}
}
call_user_func( self::$error_callback ); }
}
}

轻量级router[类似laravel router]的更多相关文章

  1. vue router.push(),router.replace(),router.go()和router.replace后需要返回两次的问题

    转载:https://www.cnblogs.com/lwwen/p/7245083.html https://blog.csdn.net/qq_15385627/article/details/83 ...

  2. vue 中router.go;router.push和router.replace的区别

    vue 中router.go:router.push和router.replace的区别:https://blog.csdn.net/div_ma/article/details/79467165 t ...

  3. vue中router.go、router.push和router.replace的区别

    router.go(n) 这个方法的参数是一个整数,意思是在history记录中向前或者后退多少,类似window.history.go(n) router.push(location) 想要导航到不 ...

  4. vue 中router.go、router.push和router.replace的区别

    router.go(n) 这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n) router.push(location) 想要 ...

  5. 【react router路由】<Router> <Siwtch> <Route>标签

    博客 https://www.jianshu.com/p/ed5e56994f13?from=timeline 文档 http://react-guide.github.io/react-router ...

  6. [Angular 2] Router basic and Router Params

    When we define router in Angualr 2, we use @RouteConcfig() When we want to display component, we use ...

  7. $router.query和$router.params的区别

    类型于get(query) 和 post(params) 1.query方式传参和接收参数   传参: this.$router.push({ path:"/xxx" query: ...

  8. 【Vue】【Router】手动跳转用 this.$router.push() 时 $router 未定义的问题

    初入Vue,手写路由跳转时的问题: toXxxRoute: () => { this.$router.push({'path': '/xxx', 'name': 'xxx'}) } 由于使用了箭 ...

  9. .6-浅析express源码之Router模块(2)-router.use

    这一节继续深入Router模块,首先从最常用的use开始. router.use 方法源码如下: proto.use = function use(fn) { var offset = 0; var ...

随机推荐

  1. Web前端性能优化教程07:精简JS 移除重复脚本

    本文是Web前端性能优化系列文章中的第七篇,主要讲述内容:精简Javascript代码,以及移出重复脚本.完整教程可查看:  一.精简javascript 基础知识 精简:从javascript代码中 ...

  2. 操作系统也谈"算法"

    前言: 近来在准备校招的笔试面试,复习到操作系统时感觉概念性的东西比较多,不过对于以下的几类算法还是有必要做个小小总结. [作业调度算法] 先来先服务(FCFS, First Come First S ...

  3. 非编码RNA

    生命的基本过程是从DNA转录成mRNA,再翻译成蛋白质发挥功能.DNA就像一张绝密的密码图,不能随意被移动,只能被锁在细胞核里.要想知道这些密码,只能像复印一样,将密码图复印到mRNA上,由它们把这些 ...

  4. Leetcode #2 Add two number

    Q: You are given two linked lists representing two non-negative numbers. The digits are stored in re ...

  5. 【BZOJ-4636】蒟蒻的数列 动态开点线段树 ||(离散化) + 标记永久化

    4636: 蒟蒻的数列 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 247  Solved: 113[Submit][Status][Discuss ...

  6. CruiseControl.NET/CCNET安装包下载

    链接:http://pan.baidu.com/s/1bHgeCI 密码:d7q1

  7. C#的Invoke和BeginInvoke

    在Invoke或者BeginInvoke的使用中无一例外地使用了委托Delegate,至于委托的本质请参考我的另一随笔:对.net事件的看法. 一.为什么Control类提供了Invoke和Begin ...

  8. ( 译、持续更新 ) JavaScript 上分小技巧(二)

    考虑到文章过长,不便于阅读,这里分出第二篇,如有后续,每15个知识点分为一篇... 第一篇地址:( 译.持续更新 ) JavaScript 上分小技巧(一) 第三篇地址:( 译.持续更新 ) Java ...

  9. HDU 1425 sort(堆排序/快排/最大堆/最小堆)

    传送门 Description 给你n个整数,请按从大到小的顺序输出其中前m大的数. Input 每组测试数据有两行,第一行有两个数n,m(0<n,m<1000000),第二行包含n个各不 ...

  10. SaltStack之无Master和多Master(九)

    SaltStack之无Master和多Master Masterless架构,无Master 实现方式: 1)关闭minion进程 2)修改配置文件 vi /etc/salt/minion file_ ...