Minimal PHP request handler

tl;dr WaterPipe and Slim are effective request and response handlers for minimal PHP apps.

Most PHP applications I work with either need a powerful API framework (like ♥️Symfony) or CMS (like ♥️TYPO3).

A minimal PHP app however, which needs to react to two or three endpoints only, may not need more than a single PHP file containing a lamdba function for each route eventually.

I like using one of the two frameworks WaterPipe and Slim for these requirements. They are the ideal tools to create a very limited API to consume, repurpose, or publish data. And due to the reduced complexity they are the best course of action for rapid prototyping.

WaterPipe

Install WaterPipe.

composer require elementaryframework/water-pipe

Add a file public/index.php.

<?php

require __DIR__ . '/../vendor/autoload.php';

use ElementaryFramework\WaterPipe\WaterPipe;
use ElementaryFramework\WaterPipe\HTTP\Request\Request;
use ElementaryFramework\WaterPipe\HTTP\Response\Response;

$app = new WaterPipe;

// homepage
$app->get('/', static function (Request $request, Response $response) {
    $response->sendHtml('Endpoints: <ul><li>/build</li></ul>');
});

// build endpoint
$app->post('/build', static function (Request $request, Response $response) {
    $data = $request->getBody()->toArray();

    $response->sendJson([
        'success' => true,
        'token' => $data['token']
    ]);
});

$app->run();

Spin up the PHP development server.

php -S localhost:8080 -t public

Send example requests with HTTPie.

http 127.0.0.1:8080/ # GET homepage
http 127.0.0.1:8080/build/ token=foo # POST JSON Build endpoint

Slim

WaterPipe is straightforward with a limited set of methods. It does one thing, and it does it well.

If the app should comply to PSR-7 and wrap logic into middleware layers, then you may want to use Slim instead.

Install Slim and required PSR-7 implementations.

composer require slim/slim
composer require slim/psr7 slim/http

The code of the WaterPipe example above looks like this in Slim:

<?php

require __DIR__ . '/../vendor/autoload.php';

use Slim\Factory\AppFactory;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;

$app = AppFactory::create();

// homepage
$app->get('/', function (Request $request, Response $response) {
    $response->getBody()->write('Endpoints: <ul><li>/build</li></ul>');
    return $response;
});

// build endpoint
$app->post('/build/', function (Request $request, Response $response) {
    $data = $request->getParsedBody();

    return $response->withJson([
        'success' => true,
        'token' => $data['token']
    ]);
});

$app->run();

The response is build a bit differently, but the rest is similar. Plus, you now may add middleware like authentication or spam protection.

Next steps

If requirements for your app grow, then you will need to refactor it into a flexible framework. Don't keep adding logic to the lambda functions. And please, don't try to write your own framework. Also consider leaving the app as is, and add microservices for new, independent components instead.

Update: The examples return blank HTML snippets. Missing a doctype and having boring default browser styles. Checkout the package pixelbrackets/html5-mini-template whenever you want to return a valid HTML5 document with a minimal stylesheet, but don't want to set up views in a template engine for a one line message nevertheless.

$template = new \Pixelbrackets\Html5MiniTemplate\Html5MiniTemplate();
$template->setStylesheet('picnic');
$template->setContent('<h1>Endpoints</h1><ul><li>/build</li></ul>');
$message = $template->getMarkup();

⌛ Warning! This post is old. The information may be outdated.

No comments on this notepad. If you would like to add something, then dont hesitate to contact me via E-Mail or Twitter.