FastRoute Test Demo

FastRoute Test Demo With PHP

Website:Fast request router for PHP

PregRoute.class

`

<?php

class PregRoute
{
    const NOT_FOUND = 404;
    const FOUND     = 200;

    /**  ~^/user/([^/]+)/(\d+)$~
     *   ~^/user/(\d+)$~
     *   ~^/user/([^/]+)$~
     * @var string  单个正则
     */
    protected $single_regex = '~^/user/([^/]+)/(\d+)$~';

    /** 基于位置匹配
     * @var string 多个路由匹配规则
     */
    protected $combined_position_regex = "
                ~^(?:
                    /user/([^/]+)/(\d+)
                  | /user/(\d+)
                  | /user/([^/]+)
                )$~x";

    /** 位置匹配数据
     * @var array
     */
    protected $route_data_position = [
        1 => ['handler0', ['name', 'id']], # /user/tom/1   regex=>  /user/([^/]+)/(\d+)
        3 => ['handler1', ['id']],         # /user/1       regex=>  /user/(\d+)
        4 => ['handler2', ['name']],       # /user/tom     regex=>  /user/([^/]+)
    ];

    /** 基于计数匹配
     * @var string 多个路由匹配规则
     */
    protected $combined_count_regex = "
                ~^(?|
                    /user/([^/]+)/(\d+)
                  | /user/(\d+)()()
                  | /user/([^/]+)()()()
                )$~x";

    /** 基于计数匹配,只修改 ?:
     * @result 将 ?: 换成 ?| 可以组号重置,但
     *          | /user/(\d+)
     *          | /user/([^/]+) 的count都相同,采用()进行个数填充,也可以使用其它方式,如
     *          <result1>/user/(\d+)
     *          <result2>/user/([^/]+)
     * @var string
     */
    protected $combined_count_regex2 = "
                ~^(?|
                    /user/([^/]+)/(\d+)
                  | /user/(\d+)
                  | /user/([^/]+)
                )$~x";

    /** 计数匹配数据
     * @var array
     */
    protected $route_data_count = [
        3 => ['handler0', ['name', 'id']], # /user/tom/1   regex=>  /user/([^/]+)/(\d+)
        4 => ['handler1', ['id']],         # /user/1       regex=>  /user/(\d+)
        5 => ['handler2', ['name']],       # /user/tom     regex=>  /user/([^/]+)
    ];

    /** 块正则表达式
     * @var array
     */
    protected $combined_count_regexes = [];

    /** 块正则表达式数据
     * @var array
     */
    protected $route_data_counts = [];

    /** 基于位置调度路由
     * @param $url
     * @way 基于组位置的非分块
     * @result 单个占位符的情况下提供了相当好的性能
     *          占位符过多,在最坏的情况下(最后一条路线匹配),性能下降到比普通方法慢两倍以上的程度
     * @return array
     */
    public function dispatchPosition($url)
    {
        if(!preg_match($this->combined_position_regex,$url,$matches)) {
            return [self::NOT_FOUND];
        }
        //$i找到第一个非空偏移量并查找了相关数据后
        //可以通过继续遍历$matches数组并将值与变量名配对来填充占位符变量。
        for($i = 1; '' === $matches[$i]; ++$i);
        list($handler, $varNames) = $this->route_data_position[$i];
        $vars = [];
        foreach ($varNames as $varName) {
            $vars[$varName] = $matches[$i++];
        }
        return [self::FOUND, $handler, $vars];
    }

    //++++++++++++++++++++++++++++++++++++++++
    // 组号重置:
    //  PCRE regex 语法:
    //  (?| ... )是非捕获组类型。
    //  (?:和之间的区别在于 ,(?|后者将重置其包含的每个分支中的组号
    //++++++++++++++++++++++++++++++++++++++++

    /** 基于计数调度路由
     * @param $url
     * @return array
     */
    public function dispatchCount($url)
    {
        if(!preg_match($this->combined_count_regex,$url,$matches)) {
            return [self::NOT_FOUND];
        }
        list($handler, $varNames) = $this->route_data_count[count($matches)];
        $vars = [];
        $i = 0;
        foreach ($varNames as $varName) {
            $vars[$varName] = $matches[++$i];
        }
        return [self::FOUND, $handler, $vars];
    }

    /** 基于计数调度路由,非()占位
     * @param $url
     * @return array
     */
    public function dispatchCount2($url)
    {
        if(!preg_match($this->combined_count_regex2,$url,$matches)) {
            return [self::NOT_FOUND];
        }
        var_dump($matches);
    }

    /** 块正则表达式调度
     * @param $url
     * @return array
     */
    public function dispatchBlock($url)
    {
        foreach ($this->combined_count_regexes as $i => $regex) {
            if (!preg_match($regex, $url, $matches)) {
                continue;
            }

            list($handler, $varNames) = $this->route_data_counts[$i][count($matches)];

            $vars = [];
            $i = 0;
            foreach ($varNames as $varName) {
                $vars[$varName] = $matches[++$i];
            }
            return [self::FOUND, $handler, $vars];
        }
    }

    //+++++++++++++++++++++++++++++++++++++++++
    //组合的正则表达式方法对于少量的正则表达式非常有效,
    //但是如果涉及许多正则表达式则不是最佳选择,而如果每个规则有多个捕获组则则是灾难性的。
    //通过仅组合大约十个表达式的块可以提高性能。
    //这不仅可以总体上提高性能,而且可以解决多组情况下性能特别差的问题。
    //一旦开始使用分块,基于组计数的替代方法就不会有太大的区别。
    //捕获组较少时,情况稍差一些,而许多组则稍好一些。特别是对于路由,通常每条路由涉及多个占位符,基于组计数的方法似乎更可取。
    //另一方面,对于词法分析,每个标记通常仅使用一个捕获组,因此基于位置的方法将获胜。
    //+++++++++++++++++++++++++++++++++++++++++
}

$testClass = new PregRoute();
$url = '/user/tom'; #/user/1 | /user/tom/1
$dispatchPosition   = $testClass->dispatchPosition($url);
$dispatchCount      = $testClass->dispatchCount($url);
var_dump($dispatchPosition);
var_dump($dispatchCount);

`

阅读 481

推荐阅读