Handle Routes
Using A Named Class Method
You could specify a custom class method to call when the middleware executes using one of the following formats:
'ClassName::methodName'
: lazy instantiate the object;[Object, 'methodName']
: pre-instantiate the object.
For example:
require '../vendor/autoload.php';
$app = new \BitFrame\Application;
/* 1: define controller class
*
* use \Psr\Http\Message\ServerRequestInterface as Request;
* use \Psr\Http\Server\RequestHandlerInterface as Handler;
* use \Psr\Http\Message\ResponseInterface as Response;
*
* class SomeController
* {
* public function someMethod(Request $request, Handler $handler): Response
* {
* $name = $request->getAttribute('name');
*
* $response = $handler->handle($request);
* $response->getBody()->write("Hello, $name");
*
* return $response;
* }
* }
*/
// 2: define route
$app->get('/hello/{name}', 'SomeController::someMethod');
$app->get('/hello/{name}', [new SomeController, 'someMethod']);
$app->run([
\BitFrame\Message\DiactorosResponseEmitter::class,
\BitFrame\Router\FastRouteRouter::class
]);
If instantiating your route controller class does not require any arguments to be supplied, then you may want to use the lazy instantiation method as it may be good for performance.
Anonymous Class With Named Class Method
PHP 7+ allows us to create anonymous classes. If you wanted to can call a specific class method in an anonymous class (when the route is handled), you could do so by using the format: [@AnonymousClass, 'methodName']
like so:
use \Psr\Http\Message\ServerRequestInterface; use \Psr\Http\Message\ResponseInterface; use \Psr\Http\Server\RequestHandlerInterface; require '../vendor/autoload.php'; $app = new \BitFrame\Application; // define route $app->get('/hello/{name}', [new class { public function someMethod( ServerRequestInterface $request, RequestHandlerInterface $handler ): ResponseInterface { $name = $request->getAttribute('name'); $response = $handler->handle($request); $response->getBody()->write("Hello, $name"); return $response; } }, 'someMethod']); $app->run([ \BitFrame\Message\DiactorosResponseEmitter::class, \BitFrame\Router\FastRouteRouter::class ]);
Using A MiddlewareInterface
Instance
A route itself can be treated as a middleware (i.e. if the router you're using implements such functionality — for example \BitFrame\Router\FastRouteRouter
). In such instances, a router handler class must implement \Psr\Http\Server\MiddlewareInterface
so that when the router middleware (including the route itself) is processed (as per the PSR-15 spec) the process()
method is automatically called, for example:
require '../vendor/autoload.php';
$app = new \BitFrame\Application;
/* 1: define controller class
*
* use \Psr\Http\Message\ServerRequestInterface as Request;
* use \Psr\Http\Server\RequestHandlerInterface as Handler;
* use \Psr\Http\Message\ResponseInterface as Response;
* use \Psr\Http\Server\MiddlewareInterface;
*
* class SomeController implements MiddlewareInterface
* {
* public function process(Request $request, Handler $handler): Response
* {
* $name = $request->getAttribute('name');
*
* $response = $handler->handle($request);
* $response->getBody()->write("Hello, $name");
*
* return $response;
* }
* }
*/
// 2: define route
$app->get('/hello/{name}', new SomeController);
$app->run([
\BitFrame\Message\DiactorosResponseEmitter::class,
\BitFrame\Router\FastRouteRouter::class
]);
Anonymous Class
In PHP 7+, you could use anonymous classes implementing \Psr\Http\Server\MiddlewareInterface
like so:
use \Psr\Http\Message\ServerRequestInterface; use \Psr\Http\Message\ResponseInterface; use \Psr\Http\Server\RequestHandlerInterface; use \Psr\Http\Server\MiddlewareInterface; require '../vendor/autoload.php'; $app = new \BitFrame\Application; // define route $app->get('/hello/{name}', new class implements MiddlewareInterface { public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ): ResponseInterface { $name = $request->getAttribute('name'); $response = $handler->handle($request); $response->getBody()->write("Hello, $name"); return $response; } }); $app->run([ \BitFrame\Message\DiactorosResponseEmitter::class, \BitFrame\Router\FastRouteRouter::class ]);
Using The Magic __invoke
require '../vendor/autoload.php';
$app = new \BitFrame\Application;
/* 1: define controller class
*
* use \Psr\Http\Message\ServerRequestInterface as Request;
* use \Psr\Http\Message\ResponseInterface as Response;
*
* class SomeController
* {
* public function __invoke(Request $request, Response $response, callable $next)
* {
* $name = $request->getAttribute('name');
* $response->getBody()->write("Hello, $name");
*
* return $response;
* }
* }
*/
// 2: define route
$app->get('/hello/{name}', new SomeController);
$app->run([
\BitFrame\Message\DiactorosResponseEmitter::class,
\BitFrame\Router\FastRouteRouter::class
]);
Using Functions
Anonymous Functions:
use \Psr\Http\Message\ServerRequestInterface as Request; use \Psr\Http\Message\ResponseInterface as Response; require '../vendor/autoload.php'; $app = new \BitFrame\Application; // define route $app->get('/hello/{name}', function (Request $request, Response $response, callable $next) { $name = $request->getAttribute('name'); $response->getBody()->write("Hello, $name"); return $response; }); $app->run([ \BitFrame\Message\DiactorosResponseEmitter::class, \BitFrame\Router\FastRouteRouter::class ]);
Named Functions:
use \Psr\Http\Message\ServerRequestInterface as Request; use \Psr\Http\Message\ResponseInterface as Response; require '../vendor/autoload.php'; $app = new \BitFrame\Application; // 1: define controller function function controller(Request $request, Response $response, callable $next) { $name = $request->getAttribute('name'); $response->getBody()->write("Hello, $name"); return $response; } // 2: define route $app->get('/hello/{name}', 'controller'); $app->run([ \BitFrame\Message\DiactorosResponseEmitter::class, \BitFrame\Router\FastRouteRouter::class ]);
Recommendation
We recommend you use named class methods, because:
- Using a
MiddlewareInterface
instance would only work if the router you're using supports running the route as a middleware; - The magic
__invoke
and using functions may lead to issues with typehinting because$next
ascallable
is not type safe as there's no way of ensuring that thecallable
is actually able to accept the arguments passed to it.