Belin Framework

Belin Framework Cookbook

Practical installation, routing, middleware, validation, queue, storage, and JSON recipes for the Belin PHP framework.

Updated 2025-12-16T23:50:19Z Builds from COOKBOOK.md via Go
Quickstart

From composer create to dev server in minutes.

Copy the install snippet, configure .env, and boot the PHP server instantly.

Routing & Middleware

Secure defaults and REST-friendly routes.

Guard with CSRF, rate limiting, and per-route middleware while keeping controller fallbacks flexible.

Queues & JSON

Async jobs plus precise JSON helpers.

Redis-backed queues and JSON pointer utilities make background work and response shaping predictable.

Belin Framework Cookbook

Practical steps to install, configure, build, and ship apps with Belin. Start with a clean .env, wire up DB/Redis, learn the HTTP core, then use Craft to scaffold and ship.

1) Introduction & Installation

Install

composer create-project belinframework/framework my-project
cd my-project
php craft env:init        # creates .env from .env.example
composer install          # if needed

Project layout

  • public/index.php — front controller
  • config/*.php — core config; config/env/<env>/*.php overrides
  • src/Controller, src/Middleware, src/Core, src/Validation
  • tests/ — PHPUnit
  • craft — CLI entrypoint

2) Environment & Configuration

  • Edit .env (and optionally .env.<APP_ENV>) with:
    • App: APP_ENV (development/production), APP_DEBUG, APP_MAX_REQUEST_BODY
    • Database: DB_HOST/PORT/NAME/USER/PASSWORD
    • Queue: QUEUE_DRIVER=sync|redis, REDIS_*
    • Storage: STORAGE_ROOT
    • Security: CORS_ALLOWED_ORIGINS, CSRF_*, SECURITY_*, TRUSTED_PROXIES
  • Env-specific overrides live in config/env/<APP_ENV>/*.php and load after the base config.
  • Per-env files: if APP_ENV=development, .env.development loads after .env.
  • Run the dev server:
php craft serve          # http://localhost:8000 by default
php craft serve localhost:8080

3) Core HTTP Stack

Routing

Define routes in config/routes.php:

$router->get('/', [WelcomeController::class, 'index']);
$router->get('/api/status', [StatusController::class, 'index']);

$router->group(['prefix' => '/api', 'middleware' => [
    // \App\Middleware\AuthHeaderMiddleware::class,
]], function (Router $r) {
    $r->resource('/posts', \App\Controller\PostController::class); // RESTful routes
});

Optional controller fallback:

$router->enableControllerFallback(); // /user/profile -> UserController::profile()

Middleware

  • Global middleware: config/app.php (app.middleware).
  • Per-route middleware: third argument on routes or group middleware.
  • Included: SecurityHeadersMiddleware, CsrfMiddleware, RateLimitMiddleware.
  • Custom middleware implements MiddlewareInterface::handle(Request $request, callable $next).

Requests & Responses

  • Request (App\Core\Request): input(), query(), json(), file(), has(), filled(), route('id'), ip(), isJson(), isSecure(), isAjax(), getRawBody().
  • Validation: $request->validate($rules) throws ValidationException on failure.
  • Response (App\Core\Response): success(), error(), created(), noContent(), notFound(), unauthorized(), forbidden(), validationError(), json(), redirect(), withHeader(), withCookie() (secure defaults).

Validation example

$data = $request->validate([
    'email' => 'required|email',
    'age' => 'integer|min_value:18',
    'role' => 'in:admin,user,viewer',
]);

Rules: required, email, string, integer|int, float|numeric, boolean|bool, array, url, uuid, slug, min, max, between, min_value, max_value, in, regex. Messages/patterns: config/validation.php.

4) Data & Background Work

Storage helper

App\Core\Storage keeps file ops inside STORAGE_ROOT:

$storage = new Storage();
$path = $storage->path('uploads', 'file.txt');
$storage->write($path, 'hello');
$contents = $storage->read($path);
$storage->append($path, ' world');

Config: config/storage.php (root, subpaths, permissions).

JSON helper

App\Core\Json:

$data = Json::decode($json);
$email = Json::pointerGet($data, '/user/email');
Json::pointerSet($data, '/flags/active', true);
$merged = Json::mergePatch($data, $patch);
$encoded = Json::encode($merged, pretty: true);

Queues & jobs

  • Configure driver in .env: QUEUE_DRIVER=sync or QUEUE_DRIVER=redis with REDIS_*.
  • Job shape:
use App\Queue\JobInterface;
use App\Core\Container;

class SendEmailJob implements JobInterface {
    public function __construct(private array $payload = []) {}
    public function handle(Container $container): void { /* send mail */ }
    public function toArray(): array { return $this->payload; }
    public static function fromArray(array $data): self { return new self($data); }
}
  • Dispatch:
$queue = new \App\Queue\QueueManager();
$queue->push(new SendEmailJob(['to' => 'user@example.com']));
  • Work:
php craft queue:work --sleep 500   # respects QUEUE_DRIVER

Events & legacy worker

  • queue:worker runs the Redis-backed event bus (App\Core\EventBus).
  • Prefer queue:work for new jobs; keep queue:worker if you rely on the legacy event bus.

5) Security, Errors, Testing

  • Error handling: JSON errors; stack traces only when APP_DEBUG=true.
  • CORS/CSRF/Security: config-driven; defaults are locked down (CORS_ALLOW_CREDENTIALS=false, limited origins unless set).
  • Trusted proxies: set TRUSTED_PROXIES (comma-separated IPs) to honor X-Forwarded-For/Proto.
  • Request size: capped via APP_MAX_REQUEST_BODY (413 when exceeded).
  • Testing:
vendor/bin/phpunit

Includes coverage for router, middleware, storage, JSON, validation, config env, and queue (sync).

6) Craft CLI Workflow

List all commands:

php craft list

High-velocity commands:

  • env:init [--force] — seed .env from example.
  • Make scaffolds: make:controller <Name>, make:service <Name>, make:middleware <Name>, make:validation <Name>, make:error <Name>, make:core <Name>, make:entity|make:model <Name>, make:migration <Name>, make:event <Name>, make:listener <Name> [Event], make:crud <Name>, make:test <Name> [--unit|--integration].
  • Routing helpers: make:route <path> <Ctrl@method> [VERB] or --resource.
  • Runtime: serve [host:port], queue:work [--sleep ms], queue:worker [--poll ms] [--batch n], tinker (REPL), delete <type> <name>.

7) Tips & Best Practices

  • Keep APP_DEBUG=false in production.
  • Set precise CORS_ALLOWED_ORIGINS; avoid * with credentials.
  • Prefer QUEUE_DRIVER=redis and supervise queue:work for async tasks.
  • Use config/env/<env> overrides instead of editing base configs.
  • Secure cookies/session when using cookie-based auth; prefer stateless tokens for APIs.