路由类

Router.php

<?php

class Router
{
    private $routes = [];
    private $routeCount = 0;

    public function addRoute($method, $url, $callback)
    {
        $this->routes[] = ['method' => $method, 'url' => $url, 'callback' => $callback];
        $this->routeCount++;
    }

    public function doRouting()
    {
        $is_match=0;
        // I used PATH_INFO instead of REQUEST_URI, because the
        // application may not be in the root direcory
        // and we dont want stuff like ?var=value
        $reqUrl = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);//$_SERVER['PATH_INFO'];

        if ($reqUrl == null) {
            $reqUrl = '';
        }
       

        $reqMet = $_SERVER['REQUEST_METHOD'];

        foreach ($this->routes as $route) {
            // convert urls like '/users/:uid/posts/:pid' to regular expression

             
            $patterns = array('/\[[a-zA-Z0-9\_\-\/]+\]/','/\[{[a-zA-Z0-9\_\-}]+\]/','/\[\/{[a-zA-Z0-9\_\-}]+\]/','/{[a-zA-Z0-9\_\-}]+/');
            $replace = array('([a-zA-Z0-9\-\_\/]*)','([a-zA-Z0-9\-\_]*)','([a-zA-Z0-9\-\_\/]*)','([a-zA-Z0-9\-\_]+)');


            // $pattern = "@^" . preg_replace('/\\\:[a-zA-Z0-9\_\-]+/', '([a-zA-Z0-9\-\_]+)', preg_quote($route['url'])) . "$@D";
            $pattern = "@^" . preg_replace($patterns, $replace, $route['url']) . "$@D";

            $matches = array();
            // check if the current request matches the expression
            if (preg_match($pattern, $reqUrl, $matches)) {
                // remove the first match
                array_shift($matches);

                foreach ($matches as $key => $value) {
                    if (empty($value)) {
                        unset($matches[$key]);
                    }
                }
                // call the callback with the matched positions as params

                if ($route['method'] !=='*'  && $reqMet !=='HEAD'  && (
                    !empty($route['method']) &&
                    !in_array($reqMet, explode(',', $route['method'])))
                ) {
                    throw new Exception("405 Not Allowed");
                }
                

                return call_user_func_array($route['callback'], $matches);
            } else {
                $is_match++;
            }
        }

        if ($is_match == $this->routeCount) {
            throw new Exception("404 Not Found");
        }
    }
}


//autoload
// spl_autoload_register(function ($class_name) {
//     require_once __DIR__ . '/' .  str_replace('\\', '/', $class_name) . '.php';
// });

 

路由配置文件

config/route.php

<?php
return [


    [
        ['GET'],
        '/',
        [new App\Index, 'index'],
    ],
    [
        ['GET'],
        '/search',
        [new App\Index, 'search'],
    ],

    [
        ['GET'],
        '/tool-[id][/]',
        [new App\Index, 'tool'],
    ],

    [
        ['GET'],
        '/tool-[id]',
        [new App\Index, 'tool'],
    ],



    [
        ['GET'],
        '/category-[cid].html',
        [new App\Index, 'category'],

    ],


    [
        ['PUT,GET'],
        '/hello',
        function () {
            echo 'Hello AmazePHP!';
        },
    ],

    [
        ['GET'],
        '/hello2',
        'callbackFunction',
    ],

    [
        ['GET'],
        '/hello44.php',
        function () {
            include 'App/aaaaa.php';
        },
    ],

    [
        ['GET'],
        '/hello3/[id]',
        [new App\Foo, 'bar'],////object, method
    ],

    [
        ['GET'],
        '/a/[uid]/b[/pid]',
        ['App\myclass', 'say_hello'],//static method
    ],

    [
        ['GET,POST'],
        '/users',
        function () {
            echo 'post AmazePHP';
        },
    ],

    [
        ['*'],
        '/users/[uid]/posts/[pid]',
        function ($uid, $pid = 99) {
            var_dump($uid, $pid);
        },
    ],

 
    ];

 

使用方法

index.php

include 'lib/Router.php';
include 'config/route.php';

$router = new Router();
foreach (config('route') as $key => $value) {
        $router->addRoute($value[0][0], $value[1], $value[2]);
}

$router->doRouting();

 

最后更新于 2023年7月3日

PHP单文件路由类
标签: