Skip to content

Instantly share code, notes, and snippets.

@alanpich
Created March 3, 2015 16:42
Show Gist options
  • Save alanpich/2fee1bca55d5f0a55c31 to your computer and use it in GitHub Desktop.
Save alanpich/2fee1bca55d5f0a55c31 to your computer and use it in GitHub Desktop.
Concept for nestable routers in Slim
<?php
use Slim\Router2 as Router;
use Slim\App2 as App;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
require dirname(__DIR__).'/vendor/autoload.php';
$app = new App();
$app->get('/foo',function(Request $request, Response $response){
echo "This is /foo";
return $response;
});
$app->get('/foo/{bar}',function( Request $request, Response $response){
echo "This is /foo/{bar}";
return $response;
});
$myChildRouter = new Router();
$myChildRouter->get('/fwibble',function( Request $request, Response $response ){
echo "This is /baz/fwibble";
return $response;
});
$app->mount('/baz', $myChildRouter);
$app->run();
<?php
namespace Slim;
use FastRoute\Dispatcher;
use FastRoute\Dispatcher\GroupCountBased;
use \Slim\Router2 as Router;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class App2 extends Router
{
public function run(){
$request = Request::createFromGlobals();
$response = new Response();
$routeData = $this->getData();
$dispatcher = new GroupCountBased($routeData);
$routeInfo = $dispatcher->dispatch($request->getMethod(), $request->getRequestUri());
switch ($routeInfo[0]) {
case Dispatcher::NOT_FOUND:
// ... 404 Not Found
die("404 Not Found");
break;
case Dispatcher::METHOD_NOT_ALLOWED:
$allowedMethods = $routeInfo[1];
// ... 405 Method Not Allowed
die("405 Method Not Allowed, Should be one of ".implode(", ",$allowedMethods));
break;
case Dispatcher::FOUND:
$handler = $routeInfo[1];
$vars = $routeInfo[2];
$request->pseudoMethod_setRouteParams($vars)
$handler($request,$response);
break;
}
}
}
<?php
namespace Slim;
use FastRoute\DataGenerator;
use FastRoute\RouteCollector;
use FastRoute\RouteParser;
class Router2 extends RouteCollector
{
private $routeParser;
private $dataGenerator;
protected $middleware = [];
protected $childRouters = [];
protected $pathPrefix = '';
public function __construct(RouteParser $routeParser = null){
$this->routeParser = ($routeParser instanceof RouteParser)? $routeParser : new RouteParser\Std();
$this->dataGenerator = new FastRoute\DataGenerator();
}
public function setPathPrefix($prefix){
$this->pathPrefix = $prefix;
}
/**
* Add one or more middleware functions to this router
* to be executed in order before all routes
*
* @param $middleware
*/
public function add($middleware){
if(is_array($middleware)){
foreach($middleware as $mw){
$this->add($mw);
}
return;
}
$this->middleware[] = $middleware;
}
/**
* Adds a route to the collection.
*
* The syntax used in the $route string depends on the used route parser.
*
* @param string $httpMethod
* @param string $route
* @param mixed $handler
*/
public function addRoute($httpMethod, $route, $handler) {
$routeData = $this->routeParser->parse($route);
$this->dataGenerator->addRoute($httpMethod, $routeData, $handler);
}
public function get(){
$middleware = func_get_args();
if(count($middleware) < 2){
throw new \InvalidArgumentException("Not enough arguments to create route");
}
$route = array_shift($middleware);
$handler = array_shift($middleware);
$this->addRoute('GET',$route,$handler);
}
public function post($route, $handler){
$middleware = func_get_args();
if(count($middleware) < 2){
throw new \InvalidArgumentException("Not enough arguments to create route");
}
$route = array_shift($middleware);
$handler = array_shift($middleware);
$this->addRoute('POST',$route,$handler);
}
public function put($route,$handler){
$middleware = func_get_args();
if(count($middleware) < 2){
throw new \InvalidArgumentException("Not enough arguments to create route");
}
$route = array_shift($middleware);
$handler = array_shift($middleware);
$this->addRoute('PUT',$route,$handler);
}
public function getData()
{
// Set the route prefix for this router (if any)
$this->dataGenerator->setRoutePrefix($this->pathPrefix);
$data = $this->dataGenerator->getData();
foreach($this->childRouters as $crs){
list($path,$router) = $crs;
$childData = $router->getData();
$data[0] = array_merge($data[0],$childData[0]);
$data[1] = array_merge($data[1],$childData[1]);
}
return $data;
}
public function mount($path, Router2 $router ){
$router->setPathPrefix($path);
$this->childRouters[] = [$path,$router];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment