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. 【URAL 1297】Palindrome 最长回文子串

    模板题,,,模板打错查了1h+QAQ #include<cmath> #include<cstdio> #include<cstring> #include< ...

  2. awk打开多个文件的方法

    1.当awk读取的文件只有两个的时候,比较常用的有三种方法(1)awk 'NR==FNR{...}NR>FNR{...}' file1 file2 (2)awk 'NR==FNR{...}NR! ...

  3. C# 获取当前月第一天和最后一天

    废话不多说,直接上代码 //先获取当前时间 DateTime now = DateTime.Now; //获取当前月的第一天 DateTime d1 = new DateTime(now.Year, ...

  4. 【OpenJ_POJ C16D】Extracurricular Sports(构造,找规律)

    题目求n个互不相同的数,满足其和为其lcm.我们把lcm看成一个线段,分割成长度不同的n份.当然分法有很多,我们只需要构造一个好想好写的.先分成两个二分之一,取其中一个二分之一再分成1/3和2/3,接 ...

  5. iOS 蓝牙开发(四)BabyBluetooth蓝牙库介绍(转)

    转载自:http://www.cocoachina.com/ios/20151106/14072.html 原文作者:刘彦玮 BabyBluetooth 是一个最简单易用的蓝牙库,基于CoreBlue ...

  6. 自定义多列排序:C++/Java实现

    前言: 有些时候,我们在编程中会遇到多列排序的需求.假如在execle,这事儿就太easy了.不过没办法,现在就需要你用Java或者C++实现这样一个功能! 比如将下表无序的数据通过重排之后按照以下规 ...

  7. 学习WebSocket(一):Spring WebSocket的简单使用

    1.什么是websocket? WebSocket协议定义了一种web应用的新功能,它实现了服务器端和客户端的全双工通信.全双工通信即通信的双方可以同时发送和接收信息 的信息交互方式.它是继Java ...

  8. Hadoop-2.2.0 (传 hadoop-2.2.0.tar.gz)

    配置hadoop 2.1 上传hadoop包 2.2 解压hadoop包 首先在根目录下创建一个cloud目录 mkdir /cloud tar -zxvf hadoop-2.2.0.tar.gz - ...

  9. bzoj1103: [POI2007]大都市meg

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1103 题目大意:在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Ma ...

  10. Linux process authority、the security risks in running process with high authority

    catalog . Linux进程权限原理 . 最小权限原则 - 进程降权运行最佳实践 . 进程权限控制包含的攻防向量 . 进程高权限安全风险检查技术方案 1. Linux进程权限原理 我们知道,Li ...