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/runs or crabphp/redis, are installed the same way, with composer require.

Requirements

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