HTTP Controller

Apex utilizes PSR-7 and PSR-15 standardized methodologies for handling HTTP requests. Let's create a quick HTTP controller that displays project details on the public site. Within terminal, run the following create http-controller command:

apex create http-controller disaster project-details --route projects/:project_id

Several things will happen upon running the above command:

  • New file will be generated at /src/HttpControllers/ProjectDetails.php which is a PSR-15 compliant Middleware class.
  • New line will be added to the /boot/routes.yml file that signifies all HTTP requests to /projects/:project_id will be handled by the new HTTP controller. The colon (:) in front of "project_id" signifies a dynamic path parameter. For full information please consult the [HTTP Router[(/docs/http/router) section of the developer documentation.
  • The file at /etc/Disaster/registry.yml will have entries added for both, the HTTP controller itself and the route. This ensures both will be included upon publishing the package to the repository so everything is properly installed when another user installs the package hence why the above CLI command must contain the package name and the --route flag.

Open the newly generated file at /src/HttpControllers/ProjectDetails.php and replace it with the following contents:

declare(strict_types = 1);

namespace App\HttpControllers;

use Apex\Svc\{View, Convert};
use Nyholm\Psr7\Response;
use Psr\Http\Message\{ServerRequestInterface, ResponseInterface};
use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface};
use App\Disaster\Models\{Project, Location};

 * Http Controller - ~alias~
class ProjectDetails implements MiddlewareInterface

    private View $view;

    private Convert $convert;

     * Process request
    public function process(ServerRequestInterface $request, RequestHandlerInterface $app): ResponseInterface

        // Check if project exists
        $project_id = $app->pathParam('project_id');
        if (!$proj = Project::whereId($project_id)) {
            $html = $this->view->render('404.html');
            return new Response(404, [], $html);

        // Get project vars
        $vars = $proj->toArray();
        $vars['created_at'] = $this->convert->date($vars['created_at'], true);

        // Get location
        $loc = Location::whereId($vars['location_id']);
        $vars['location'] = $loc->getName();

        // Set template vars
        $this->view->assign('project', $vars);

        // Render project template
        $html = $this->view->render('project.html');

        // Create PSR7 compliant response

        $response = new Response(200, [], $html);

        // Return
        return $response;


The above class is a standard PSR-15 compliant middleware class, which obtains the project model instance. If the project does not exist the standard 404 template is displayed. Otherwise, the project is formatted as necessary, location is gathered and the project.html view is displayed.

View - project.html

As seen from the above PHP class, a view named "project" is rendered and displayed. Let's quickly develop out that view. Run the following create view command:

apex create view disaster project

This command will create files at /views/html/project.html and /views/php/project.php, plus will add another entry into the /etc/Disaster/registry.yml to ensure the view is included when the package is published to the repository.

Open the file at /views/html/project.html and enter the following contents:

<h1>Project Details</h1> <s:form_table> <s:ft_label label="ID" value=""> <s:ft_label label="Location" value="~project.location~"> <s:ft_label label="Date Created" value="~project.created_at~"> <s:ft_label label="Title" value="~project.title~"> <s:ft_label label="Description" value="~project.description~"> </s:form_table>


With everything in place, you may now visit (replace 1 with an id# of a project in the database), the request will be processed by the new HTTP controller, and the new project.html template will be rendered. For full information on HTTP requests and the router, please consult the HTTP Requests section of the developer documentation, or for a more brief summary the HTTP Request Handling Guide.