Simple Router for PHP framework

Source: Internet
Author: User
Tags autoload php class php framework vars
The function of routing is to distribute requests to different controllers, based on the principle of regular matching. Next, we implement a simple router, the ability to implement is for static routing (no placeholder), the correct call to callback.

For routes with placeholders, when callback is called correctly, a placeholder parameter is passed in, such as for route:/user/{id} When the request is/USER/23, the incoming parameter $args structure is

[    ' id ' = ' 23 ']

General idea

We need to manage the information for each route: the HTTP method ($method), the routing string ($route), the callback ($callback), so a Addroute method is required, and a short method is provided get,post (that is, write $method).

For a placeholder-like routing string such as/user/{id}, the placeholder is extracted and the placeholder part becomes a regular string

Realize

Route.php class

<?phpnamespace salamanderroute;class Route {/** @var String */Public $http    Method;    /** @var String */public $regex;    /** @var Array */public $variables;    /** @var Mixed * * public $handler;     /** * Constructs a route (value object).     * * @param string $httpMethod * @param mixed $handler * @param string $regex * @param array $variables */Public function __construct ($httpMethod, $handler, $regex, $variables) {$this->httpmethod = $httpMetho        D            $this->handler = $handler;        $this->regex = $regex;    $this->variables = $variables;     }/** * Tests whether this route matches the given string. * * @param string $STR * * @return BOOL */Public function matches ($str) {$regex = ' ~^ '. $this ->regex.        '$~';    return (BOOL) Preg_match ($regex, $STR); }}

dispatcher.php

<?php/** * User:salamander * DATE:2017/11/12 * time:13:43 */namespace salamanderroute;class Dispatcher {/** @var    mixed[][] */protected $staticRoutes = [];    /** @var route[][] */private $METHODTOREGEXTOROUTESMAP = [];    Const NOT_FOUND = 0;    Const FOUND = 1;    Const METHOD_NOT_ALLOWED = 2; /** * Extract Placeholder * @param $route * @return Array */Private Function Parse ($route) {$regex = ' ~^ (?:/ [A-za-z0-9_]*|/\{([a-za-z0-9_]+?)        \})+/?$~';            if (Preg_match ($regex, $route, $matches)) {//Remove full match array_shift ($matches); return [Preg_replace (' ~{[a-za-z0-9_]+?}        ~ ', ' ([a-za-z0-9_]+) ', $route), $matches,];    } throw new \logicexception (' Register route failed, pattern is illegal '); }/** * Register routing * @param $httpMethod string |      string[] * @param $route * @param $handler */Public Function Addroute ($httpMethod, $route, $handler) {  $routeData = $this->parse ($route); foreach ((array) $httpMethod as $method) {if ($this->isstaticroute ($routeData)) {$this            Addstaticroute ($httpMethod, $routeData, $handler);            } else {$this->addvariableroute ($httpMethod, $routeData, $handler);    }}} Private Function Isstaticroute ($routeData) {return count ($routeData [1]) = = = 0;        } Private Function Addstaticroute ($httpMethod, $routeData, $handler) {$routeStr = $routeData [0];                if (Isset ($this->staticroutes[$httpMethod [$routeStr])) {throw new \logicexception (sprintf (        ' Cannot register routes matching '%s ' for method '%s ', $routeStr, $httpMethod); } if (Isset ($this->methodtoregextoroutesmap[$httpMethod])) {foreach ($this->methodtoregextoroutes  map[$httpMethod] as $route) {if ($route->matches ($routeStr)) {                  throw new \logicexception (sprintf (' Static route '%s ' is shadowed by previously D                    efined variable route '%s ' for method '%s ', $routeStr, $route->regex, $httpMethod                ));    }}} $this->staticroutes[$httpMethod] [$routeStr] = $handler;        } Private Function Addvariableroute ($httpMethod, $routeData, $handler) {list ($regex, $variables) = $routeData;                 if (Isset ($this->methodtoregextoroutesmap[$httpMethod [$regex])) {throw new \logicexception (sprintf (            ' Cannot register routes matching '%s ' for method '%s ', $regex, $httpMethod        )); } $this->methodtoregextoroutesmap[$httpMethod [$regex] = new Route ($httpMethod, $handler, $regex, $v    Ariables);    Public function Get ($route, $handler) {$this->addroute (' Get ', $route, $handler); } public FunctIon Post ($route, $handler) {$this->addroute (' Post ', $route, $handler);    The public function put ($route, $handler) {$this->addroute (' Put ', $route, $handler);    Public Function Delete ($route, $handler) {$this->addroute (' delete ', $route, $handler);    Public function patch ($route, $handler) {$this->addroute (' Patch ', $route, $handler);    The Public function head ($route, $handler) {$this->addroute (' head ', $route, $handler);        /** * Distribution * @param $httpMethod * @param $uri */Public Function dispatch ($httpMethod, $uri) {        $staticRoutes = Array_keys ($this->staticroutes[$httpMethod]); foreach ($staticRoutes as $staticRoute) {if ($staticRoute = = = $uri) {return [Self::found, $this            ->staticroutes[$httpMethod] [$staticRoute], []];        }} $routeLookup = [];        $index = 1; $regexes = Array_keys ($this->methodtoregextoroutesmap[$htTpmethod]); foreach ($regexes as $regex) {$routeLookup [$index] = [$this->methodtoregextoroutesmap[$http            method][$regex]->handler, $this->methodtoregextoroutesmap[$httpMethod] [$regex]->variables,            ];        $index + = count ($this->methodtoregextoroutesmap[$httpMethod] [$regex]->variables); } $regexCombined = ' ~^ (?: '. Implode (' | ', $regexes).        ')$~';        if (!preg_match ($regexCombined, $uri, $matches)) {return [self::not_found]; } for ($i = 1; "= = = $matches [$i];        + + $i);        List ($handler, $varNames) = $routeLookup [$i];        $vars = [];        foreach ($varNames as $varName) {$vars [$varName] = $matches [$i + +];    } return [Self::found, $handler, $vars]; }}

Configuration

nginx.conf Rewrite to index.php

location/{try_files $uri $uri//index.php$is_args$args; # Pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php$ {FASTCG            I_pass 127.0.0.1:9000;                   Fastcgi_index index.php;            Fastcgi_param script_filename $document _root$fastcgi_script_name;        Include Fastcgi_params; }}composer.json automatically load {"name": "Salmander/route", "require": {}, "AutoLoad": {"psr-4": {"Salamand Erroute\\ ":" Salamanderroute/"}}} 

Composer.json Automatic loading

{    "name": "Salmander/route",    "require": {},    "AutoLoad": {      "psr-4": {        "salamanderroute\\": " salamanderroute/"      }  }

End Use

index.php

<?phpinclude_once ' vendor/autoload.php '; use salamanderroute\dispatcher; $dispatcher = new Dispatcher (); $ Dispatcher->get ('/', function () {    echo ' Hello World ';}); $dispatcher->get ('/user/{id} ', function ($args) {    echo "user {$args [' id ']} visit";});  /Fetch method and URI from somewhere$httpmethod = $_server[' Request_method ']; $uri = $_server[' request_uri '];//remove query string if (False!== $pos = Strpos ($uri, '? ')) {    $uri = substr ($uri, 0, $pos);} $routeInfo = $dispatcher->dispatch ($httpMethod, $uri); switch ($routeInfo [0]) {case    Dispatcher::not_found:        echo ' 404 Not Found ';        break;    Case Dispatcher::found:        $handler = $routeInfo [1];        $vars = $routeInfo [2];        $handler ($vars);        break;}

Look at the above case we should implement a simple router for PHP, have a clearer understanding of it, later we will continue to launch relevant articles, we have any questions can be enthusiastic to speak,

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.