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();