Installation
Introduction
Crab is a PHP framework for JSON APIs. It runs your application as a long-lived server: the code is loaded once, and worker processes then answer requests for as long as they live, without PHP-FPM, Nginx or Apache in front.
Reach for it when you are building an API and want it to start fast, answer fast and stay small enough to read. It is not a full-stack framework: there are no views, no sessions and no ORM. What you get is routing, typed actions with validation, middleware, a database layer with a query builder and migrations, authentication by token, a cache, events, a queue, a scheduler, an HTTP client and streaming responses, with durable runs and actors as packages of their own.
[!NOTE] Crab's latest release is v0.6.3, on Packagist. Its packages, such as
crabphp/runsorcrabphp/redis, are installed the same way, withcomposer require.
Requirements
- PHP 8.4 or newer.
- The
mbstringextension, which comes with most installations of PHP. - The
pcntlandposixextensions to run more than one worker or a server in the background. Without them,start --singleruns HTTP alone; runqueue:work --singleandschedule:work --singleseparately when needed. pdo_sqliteorpdo_mysqlfor the database,opensslfor callinghttpsAPIs.
Creating an application
The starting point is the skeleton, crabphp/crab. Create an application from it with Composer:
composer create-project crabphp/crab shop
cd shop
php cua dev
create-project installs the framework and writes .env from .env.example. To add Crab to a project of your own instead, require it with composer require crabphp/framework.
Open http://127.0.0.1:8080. cua is the application's command line; php cua on its own lists every command.
dev restarts the server whenever you save a file under app/, config/ or routes/, or .env, so there is nothing to restart by hand while you work. In production the server is run with start; see Deployment.
Your first route
Routes are declared in routes/web.php:
// routes/web.php
use App\Actions\SayHello;
use Crab\Route;
Route::get('/', static fn (): string => "Hello from Crab\n");
Route::get('/hello/{name}', SayHello::class);
An action is a closure or a class. The class takes the route's parameter by name and returns data, which is sent as JSON:
// app/Actions/SayHello.php
namespace App\Actions;
final class SayHello
{
/**
* @return array{hello: string}
*/
public function handle(string $name): array
{
return ['hello' => $name];
}
}
curl http://127.0.0.1:8080/hello/Ada
# {"hello":"Ada"}
One file is enough
The skeleton is a convenience, not a requirement. A whole application can be one file:
// app.php
use Crab\App;
use Crab\Route;
$app = new App();
Route::get('/', static fn (): string => "Hello, world!\n");
Route::get('/hello/{name}', static fn (string $name): array => ['hello' => $name]);
return $app;
php vendor/bin/crab app.php start --single
bin/crab takes the file that returns the application, then the command. Use this for a small service or to try something out; move to the skeleton's layout when the file grows.
Next steps
- Directory structure shows where things go.
- Request lifecycle explains what a long-running server changes about how you write PHP. Read it before writing your first service.
- Routing and Actions cover the code you will write most.