How do I use FastRoute?

I'm attempting to use the FastRoute routing library and can't get the simple usage example to work.

Here is the basic usage example found on the GitHub page:

<?php require '/path/to/vendor/autoload.php'; $dispatcher = FastRoute\simpleDispatcher(function(FastRoute\RouteCollector $r) { $r->addRoute('GET', '/users', 'get_all_users_handler'); // {id} must be a number (\d+) $r->addRoute('GET', '/user/{id:\d+}', 'get_user_handler'); // The /{title} suffix is optional $r->addRoute('GET', '/articles/{id:\d+}[/{title}]', 'get_article_handler'); }); // Fetch method and URI from somewhere $httpMethod = $_SERVER['REQUEST_METHOD']; $uri = $_SERVER['REQUEST_URI']; // Strip query string (?foo=bar) and decode URI if (false !== $pos = strpos($uri, '?')) { $uri = substr($uri, 0, $pos); } $uri = rawurldecode($uri); $routeInfo = $dispatcher->dispatch($httpMethod, $uri); switch ($routeInfo[0]) { case FastRoute\Dispatcher::NOT_FOUND: // ... 404 Not Found break; case FastRoute\Dispatcher::METHOD_NOT_ALLOWED: $allowedMethods = $routeInfo[1]; // ... 405 Method Not Allowed break; case FastRoute\Dispatcher::FOUND: $handler = $routeInfo[1]; $vars = $routeInfo[2]; // ... call $handler with $vars break; } 

Where the comment reads "... call $handler with $vars", I've tried returning call_user_func_array($handler, $vars) but it doesn't work.

I also thought that maybe it was the .htaccess file that was stopping it working, as the Github page doesn't have a .htaccess file example for the project. I'm using this:

RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . index.php [QSA,L] 

I've also tried calling a route with a closure as the handler, like so:

$r->addRoute('GET', '/', function() { echo 'home'; }); 
2

4 Answers

Example how to handle request

$r->addRoute('GET', '/users', User::class . '/getUsers'); 

Then if dispatcher found, you can process it as following

case FastRoute\Dispatcher::FOUND: $handler = $routeInfo[1]; $vars = $routeInfo[2]; list($class, $method) = explode("/", $handler, 2); call_user_func_array(array(new $class, $method), $vars); break; 

Don't forget to create class User with getUsers() method.

0

I made a demo API that uses FastRoute and PHP-DI(dependency injection) to showcase how to use both. See: . In a nutshell, it looks like this:

/** * @param string $requestMethod * @param string $requestUri * @param Dispatcher $dispatcher * @throws DependencyException * @throws NotFoundException */ private function dispatch(string $requestMethod, string $requestUri, Dispatcher $dispatcher) { $routeInfo = $dispatcher->dispatch($requestMethod, $requestUri); switch ($routeInfo[0]) { case Dispatcher::NOT_FOUND: $this->getRequest()->sendNotFoundHeader(); break; case Dispatcher::METHOD_NOT_ALLOWED: $this->getRequest()->sendMethodNotAllowedHeader(); break; case Dispatcher::FOUND: list($state, $handler, $vars) = $routeInfo; list($class, $method) = explode(static::HANDLER_DELIMITER, $handler, 2); $controller = $this->getContainer()->get($class); $controller->{$method}(...array_values($vars)); unset($state); break; } } 
$r->addRoute(['GET','POST','PUT'], '/test', 'TestClass/testMethod'); 

Then in your dispatch method:

$routeInfo = $router->dispatch($httpMethod, $uri) switch($routeInfo[0]) { case FastRoute\Dispatcher::FOUND: $handler = $routeInfo[1]; $vars = $routeInfo[2]; list($class, $method) = explode('/',$handler,2); $controller = $container->build()->get($class); $controller->{$method}(...array_values($vars)); break; } 

Class and method of course could be invoked by call_user_func(), but as I wanted the router to be more abstract and placed outside in the root directory I decided to use DI container, which is brilliant.

2

Create method homepage()

Create class User with method users().

Add routes like following

$r->addRoute(['GET','POST','PUT'], '/home', 'homepage'); $r->addRoute(['GET','POST','PUT'], '/aboutus', function() { echo 'About us'; }); $r->addRoute(['GET','POST','PUT'], '/users', 'User/users'); 

If dispatcher found

case FastRoute\Dispatcher::FOUND: $handler = $routeInfo[1]; $vars = $routeInfo[2]; if ( is_object( $handler ) || ( is_string( $handler ) && strpos( $handler, '/' ) === false ) ) { if(count($vars) > 0) { call_user_func_array($handler,$vars); } else { call_user_func_array($handler,array()); } } else if ( is_string( $handler ) && strpos( $handler, '/' ) !== false ) { list($class, $method) = explode( '/', $handler, 2 ); if ( class_exists( $class ) && method_exists( $class, $method ) ) { call_user_func_array( array( new $class(), $method ), $vars ); } } break; 

Then,

/home will call method homepage()

/aboutus will call given function object at add routes

/users will call users() method from User class

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like