PsrRouter
Basic router developped with PSR interfaces.
Other libraries wich support PSR interfaces are needed in order to use the router, $request and $response parameters.
This router supports GET, POST, PUT, DELETE, OPTIONS, PATCH methods and can handle 400, 404 and 405 errors natively.
If you use this router with Apache, don't forget to rewrite your URL in your .htaccess :, (*1)
# Options
Options -Indexes
Options +FollowSymlinks
# Rewriter URL
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ index.php [QSA,L]
Installation
composer require lordarryn/psrrouter
If you want to download the package zend-diactoros (for PSR-7 implementation) used in an example :, (*2)
composer require zendframework/zend-diactoros
Doc
Create a route :, (*3)
$app->${$method}($path, $callback);
All HTTP methods are valid (the HEAD method is native and returns only headers)., (*4)
$app->post('/my/path', function($req, $res) {
//code
return $res;
});
Using route parameters :, (*5)
$app->get('/page/{id}', function($req, $res, $slugs) {
var_dump($slugs); // array('id' => $id)
return $res;
});
Regex and route parameter :, (*6)
$app->get('/page/{id}', function($req, $res, $slugs) {
return $res;
})->regex('/[0-9]{1,3}/');
You can chain regex if you have more than one route parameter. Each regex is related to its route param in the same order that it was called., (*7)
$app->get('/route/{id}/{author}', function($req, $res, $slugs) {
return $res;
})->regex('/[0-9]{1,3}/')
->regex('/[a-z]{3,15}/');
Finally, run the router :, (*8)
$app->run($request, $response);
This method needs a Request and a Response implemented from PSR interfaces., (*9)
Examples
For this example, I use react/http server and the router. I created an other file where I wrote the routes and I include this file in the main program.
routing.php :, (*10)
get('/', function($req, $res) {
$body = $res->getBody();
$body->write(''.PHP_EOL);
$body->write('
'.PHP_EOL);
if(!empty($req->getCookieParams()['todolist'])) {
$values = explode('-', $req->getCookieParams()['todolist']);
foreach($values as $key => $todo) {
$body->write('
X '.$todo.PHP_EOL);
}
}
return $res->withBody($body);
});
//POST request : add a to-do item
$app->post('/add', function($req, $res) {
if(!empty($req->getParsedBody()['add'])) {
$add = htmlentities($req->getParsedBody()['add']);
$values = !empty($req->getCookieParams()['todolist']) ? explode('-', $req->getCookieParams()['todolist']) : array();
$values[] = $add;
$cookieHeader = 'todolist='.implode('-', $values);
return $res->withStatus(302)->withHeader('Location', '/')->withHeader('Set-Cookie', $cookieHeader);
}
return $res->withStatus(302)->withHeader('Location', '/');
});
//GET request with URL parameter : delete a to-do item
$app->get('/del-{id}', function($req, $res, $id) {
if(isset($req->getCookieParams()['todolist'])) {
$values = explode('-', $req->getCookieParams()['todolist']);
if(isset($values[$id['id']]))
unset($values[$id['id']]);
$cookieHeader = 'todolist='.implode('-', $values);
return $res->withStatus(302)->withHeader('Location', '/')->withHeader('Set-Cookie', $cookieHeader);
}
return $res->withStatus(302)->withHeader('Location', '/');
})->regex('/[0-9]{1,3}/');
?>
, (*11)
server.php :, (*12)
'text/html',
'X-Powered-By' => 'PHP '.phpversion()
)
);
//match HTTP request
return $app->run($request, $response);
});
$socket = new SocketServer(8080, $loop);
$server->listen($socket);
$loop->run();
?>
, (*13)
Another example with the zend-diactoros package :, (*14)
'text/html'
]);
$emitter = new Zend\Diactoros\Response\SapiEmitter();
$app = new PsrRouter\PsrRouter();
$app->get('/', function($req, $res) {
$body = $res->getBody();
$body->write("Hello world in {$req->getRequestTarget()} \n");
return $res->withBody($body);
});
$emitter->emit($app->run($request, $response));
?>