use route path with regular expression.
$r->addRoute('*', '[/{any:.*}]', 'ApiController@notFound');
My full code.
require 'vendor/autoload.php';
$dispatcher = \FastRoute\simpleDispatcher(function(\FastRoute\RouteCollector $r) {
$r->addRoute('GET', '/hello[/]', function() {
echo 'hello';
});
$r->addRoute('GET', '/hello/{name}', function($attribute) {
echo 'hello ' . $attribute['name'];
});
$r->addGroup('/api', function (\FastRoute\RouteCollector $r) {
$r->addRoute('GET', '/hello[/]', function() {
header('Content-type: application/json');
echo json_encode(['msg' => 'hello API']);
});
$r->addRoute('*', '[/{any:.*}]', function() {
header('Content-type: application/json');
echo json_encode(['msg' => 'not found']);
});
});
});
// Fetch method and URI from somewhere
// for dynamic subfolder. https://github.com/nikic/FastRoute/issues/110
$base = dirname($_SERVER['PHP_SELF']);
ltrim($base, '/') ? $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'], strlen($base)) : '';
// end dynamic subfolder.
$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
http_response_code(404);
echo 'not found';
break;
case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
$allowedMethods = $routeInfo[1];
// ... 405 Method Not Allowed
http_response_code(405);
echo 'method not allowed';
break;
case FastRoute\Dispatcher::FOUND:
$handler = $routeInfo[1];
$vars = $routeInfo[2];
// ... call $handler with $vars
$handler($vars);
break;
}
Tested:
- https://localhost/api => JSON 'not found'
- https://localhost/api/hello => JSON 'hello API'
- https://localhost/api/notfound => JSON 'not found'
- https://localhost/api/notfound/notfound => JSON 'not found'
- https://localhost/notfound => HTML 'not found'
Alternative
I would recommend you to use 404 route to handle this instead. It is better and easier to manage your code in the future because it will not mixed with normal route.
switch ($routeInfo[0]) {
case FastRoute\Dispatcher::NOT_FOUND:
// ... 404 Not Found
http_response_code(404);
$expUri = explode('/', $uri);
if ($expUri[1] === 'api') {
// if first url segment is api. please check this again in your application that it is [1] or [0] and correct it.
header('Content-type: application/json');
echo json_encode(['msg' => 'not found']);
} else {
echo 'not found';
}
break;
// ...
}
My full code.
<?php
require 'vendor/autoload.php';
$dispatcher = \FastRoute\simpleDispatcher(function(\FastRoute\RouteCollector $r) {
$r->addRoute('GET', '/hello[/]', function() {
echo 'hello';
});
$r->addRoute('GET', '/hello/{name}', function($attribute) {
echo 'hello ' . $attribute['name'];
});
$r->addGroup('/api', function (\FastRoute\RouteCollector $r) {
$r->addRoute('GET', '/hello[/]', function() {
header('Content-type: application/json');
echo json_encode(['msg' => 'hello API']);
});
});
});
// Fetch method and URI from somewhere
// for dynamic subfolder. https://github.com/nikic/FastRoute/issues/110
$base = dirname($_SERVER['PHP_SELF']);
ltrim($base, '/') ? $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'], strlen($base)) : '';
// end dynamic subfolder.
$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
http_response_code(404);
$expUri = explode('/', $uri);
if ($expUri[1] === 'api') {
// if first url segment is api. please check this again in your application that it is [1] or [0] and correct it.
header('Content-type: application/json');
echo json_encode(['msg' => 'not found']);
} else {
echo 'not found';
}
break;
case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
$allowedMethods = $routeInfo[1];
// ... 405 Method Not Allowed
http_response_code(405);
echo 'method not allowed';
break;
case FastRoute\Dispatcher::FOUND:
$handler = $routeInfo[1];
$vars = $routeInfo[2];
// ... call $handler with $vars
$handler($vars);
break;
}