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. 利用MVC的自定义过滤器FilterAttribute、IActionFilter、IExceptionFilter实现异常处理等功能

    今天在博客园上看了一篇推荐文章,还说得蛮有道理: http://www.cnblogs.com/richieyang/p/4779028.html 项目中确实有各种后台验证过程,最常见的莫过于判空,而 ...

  2. node.js-概念

    官方网站:http://nodejs.cn/ 1.Node 是一个服务器端 JavaScript 解释器,可是真的以为JavaScript不错的同学学习Node就能轻松拿下,那么你就错了,总结:水深不 ...

  3. c# 文件转换成base64

    private static void ReadFromFile() { FileStream fsForRead = new FileStream("c9a78c8a-29b0-410d- ...

  4. BZOJ 4245: [ONTAK2015]OR-XOR

    4245: [ONTAK2015]OR-XOR Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 492  Solved: 269[Submit][Sta ...

  5. 【bzoj3991】 寻宝游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=3991 (题目链接) 题意 给出一个n个节点的带权树,m次操作每次修改一个关键点,求每次操作后,从其中 ...

  6. Ajax请求接口加密研究(针对网页前端的接口安全加密机制研究)

    通常我们在h5前端调用后台接口时,一般是ajax,那么接口的安全成了一个问题. 这里可以肯定的说,前端调用的接口一定要验证! 然后剖析了微信网页版.京东网页版这些,也都是通过接口的形势绑定数据,所以在 ...

  7. ListView优化-ViewHolder的优化备份

    ViewHolder.java package cn.edu.bzu.util; import android.content.Context; import android.util.SparseA ...

  8. [资料搜集狂]D3.js数据可视化开发库

    偶然看到一个强大的D3.js,存档之. D3.js 是近年来十分流行的一个数据可视化开发库. 采用BSD协议 源码:https://github.com/mbostock/d3 官网:http://d ...

  9. TypeScript Basic Types(基本类型)

    在学习TypeScript之前,我们需要先知道怎么才能让TypeScript写的东西正确的运行起来.有两种方式:使用Visual studio 和使用 NodeJs. 这里我选择的是NodeJs来编译 ...

  10. Java反射机制实例解析

    1.获取想操作的访问类的java.lang.Class类的对象     2.调用Class对象的方法返回访问类的方法和属性信息     3.使用反射API来操作      每个类被加载后,系统会为该类 ...