Skip to content

Basic Handlers

Jakob Tapuć edited this page Jun 29, 2022 · 10 revisions

Introduction

Empress provides handlers for all of the most common HTTP verbs:

  • GET
  • POST
  • PATCH
  • PUT
  • DELETE
  • HEAD
  • OPTIONS

Apart from that, Empress also supports before and after filters, status mappers and exception mappers.

Registering routes

Closure collectors

Given an application object, you can register new routes using the routes() method. This method accepts any callable that takes a Routes object as its argument. All routes must be registered before the app is started.

$app = Application::create(8001);

$app->routes(function (Routes $routes) {
    $routes->delete('/', fn (Context $ctx) => /* ... */);
    $routes->get('/', fn (Context $ctx) => /* ... */);
    $routes->head('/', fn (Context $ctx) => /* ... */);
    $routes->options('/', fn (Context $ctx) => /* ... */);
    $routes->post('/', fn (Context $ctx) => /* ... */);
    $routes->patch('/', fn (Context $ctx) => /* ... */);
    $routes->put('/', fn (Context $ctx) => /* ... */);
});

Handler functions themselves are callables that accept a Context object. They are automatically run as coroutines which means that you can yield promises from them.

Attribute collectors

Empress provides a trait called AnnotatedRouteCollectorTrait that enables you to use PHP 8 attributes on plain objects to transform them into route collectors (or controllers if you squint a bit).

use Empress\Context;
use Empress\Routing\RouteCollector\AnnotatedRouteCollectorTrait;
use Empress\Routing\RouteCollector\Attribute\Route;

class IndexController
{
    use AnnotatedRouteCollectorTrait;

    #[Route('GET', '/')]
    public function index(Context $ctx)
    {
        /* ... */
    }

    #[Route('POST', '/form')]
    public function form(Context $ctx)
    {
        /* ... */
    }
}

All available verbs can be used as the first parameter to the Route attribute.

Route parameters

Route segments can be marked with a colon and a name (:param) that will be available inside the Context object as a route parameter.

#[Route('GET'), '/articles/:id')]
public function getArticle(Context $ctx)
{
    $id = $ctx['id']->to('int')->unwrap();

    // Do something with $id
}

You can have multiple parameters inside a route - /articles/:id/sortBy/:sortBy. Empress does not support matching parameters by regex - validators are flexible enough to express this succinctly in code.

Wildcards

Another useful route feature is wildcards. Wildcard is a catch-all parameter for when you don't care about its value but want to forward requests to handlers no matter what that parameter stands for. One wildcard replaces one path segment:

#[Route('GET'), '/*/articles')]

// Matches:
// GET /foo/articles
// GET /bar/articles

You can have multiple wildcards inside a route - /*/articles/*/foo.

Further reading

Check out Handler Groups for more information.