Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Action classes

While handlers are functions inside config/routes.php, the file grows with every route. A handler is moved into a separate class — an action. One class is responsible for one route, and the routes file keeps a single line.

Where actions live

Actions go into the src/Action/ folder. Slim has no command to create them: make the folder and the file by hand.

The first action

// src/Action/HomeAction.php
namespace App\Action;
 
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
 
final class HomeAction
{
    public function __invoke(Request $request, Response $response): Response
    {
        $response->getBody()->write('Blog home page');
 
        return $response;
    }
}

__invoke is a special PHP method: an object that has it can be called like a function. The arguments are the same as for a handler function.

Using it in a route

In config/routes.php the class name replaces the function:

// config/routes.php
use App\Action\HomeAction;
use Slim\App;
 
return function (App $app): void {
    $app->get('/', HomeAction::class)->setName('home');
};

Open http://localhost:8080 — the page is the same, but the handler code now has its own file. Slim creates the class object itself when a request arrives.

An action with a placeholder

Placeholders arrive as the third argument, just as in a function:

// src/Action/ShowPostAction.php
namespace App\Action;
 
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
 
final class ShowPostAction
{
    public function __invoke(Request $request, Response $response, array $args): Response
    {
        $response->getBody()->write('Post #' . (int) $args['id']);
 
        return $response;
    }
}
// config/routes.php
$app->get('/posts/{id:[0-9]+}', ShowPostAction::class)->setName('posts.show');

The address /posts/5 prints "Post #5". Remember to add use App\Action\ShowPostAction; at the top of the routes file.

Naming

An action name answers the question "what does the route do":

RouteClass
GET /postsListPostsAction
GET /posts/{id}ShowPostAction
POST /postsCreatePostAction

A controller instead of actions

If a controller — one class with several methods — feels more familiar, the route is written as an array of the class name and the method name:

// config/routes.php
$app->get('/posts', [PostController::class, 'index']);
$app->get('/posts/{id:[0-9]+}', [PostController::class, 'show']);

The index and show methods take the same arguments as __invoke. The course uses actions: each class is short and receives only what its route needs.

Common mistake

An action that parses the request, runs database queries and builds HTML all by itself turns into a "fat" class. Keep three steps in an action: take data from the request, call another class that does the work, and build the response. How to pass such classes into an action is shown in the next lesson.

Thanks for reading!

Donate to the site — we work hard for you.