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'; }); 24 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.
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.
2Create 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