Search by

Reference implementations for Front-Interop.

Package info

github.com/front-interop/impl

pkg:composer/front-interop/impl

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

1.0.0-beta2 2026-09-02 15:02 UTC

This package is auto-updated.

Last update: 2026-09-02 15:05:45 UTC


README

PDS Skeleton PDS Composer Script Names

Reference implementations of the Front-Interop interface for PHP 8.4+.

These implementations are intentionally naive; they exist to showcase the FrontController contract itself. Production front controllers would be obtained from an IOC container and would compose a request/response system, a router/dispatcher, and so on.

Installation

composer require front-interop/impl

Usage

Three reference implementations cover three execution contexts.

ConsoleFrontController

A command-line front controller, reading $argv and writing to $stdout and $stderr. Both streams are optional; they default to php://stdout and php://stderr.

use FrontInterop\Impl\ConsoleFrontController;

$front = new ConsoleFrontController($argv);
exit($front->run());

That is bin/hello.php, apart from the autoloader. Run it with:

php bin/hello.php World

RequestFrontController

An HTTP front controller, reading an injected query array and writing HTML to $output. That stream is optional; it defaults to php://output.

use FrontInterop\Impl\RequestFrontController;

$front = new RequestFrontController($_GET);
exit($front->run());

That is public/index.php, apart from the autoloader. Run composer hello at the package root, then visit:

http://localhost:8080/index.php?name=World

FrankenFrontController

A front controller for FrankenPHP, wrapping a RequestFrontController in a frankenphp_handle_request() worker loop.

use FrontInterop\Impl\FrankenFrontController;

$front = new FrankenFrontController(100);
exit($front->run());

It runs only under the FrankenPHP binary in worker mode, because frankenphp_handle_request() does not exist elsewhere.

Classes

Interface Implementation
FrontController ConsoleFrontController, RequestFrontController, FrankenFrontController

All classes are in the FrontInterop\Impl namespace. The three concrete classes extend AFrontController for the helpers they share.

Conformance

Three of the Front-Interop directives for run() shape these implementations:

  • return a status between 0 and 254
  • do not terminate the process in place of returning
  • do not let a Throwable escape

Returning a status

ConsoleFrontController returns 1 when no name is given and 0 once it has written its greeting.

RequestFrontController returns 0 after emitting its page, and 1 from error(). A 0 does not mean that nothing went wrong: it returns 0 with a 422 when no name is given, because the request was handled and a response was emitted. That counts as success in an HTTP context.

FrankenFrontController returns the status from the last request handled, set only by RequestFrontController::run(). It returns 0 if the runtime ends the loop before any request is handled.

The error() method in every controller returns 1.

Not terminating the process

None of the implementations call exit() or die(). Their callers do: bin/hello.php and public/index.php both end with exit($front->run()), so the decision to end the process belongs to the code that started it.

FrankenFrontController bounds its worker loop with $requestMax so that run() returns after that many requests. A 0 maximum defers the decision to the runtime. The loop ends when the runtime returns false.

Not letting a Throwable escape

Each implementation of run() wraps its work in a try/catch block. The catch sends the Throwable to caught(), which reports through error() and then releases the Throwable. (The release is guarded because the destructor runs at that moment, and a throw there would reach the caller after run() had already computed its status.)

Each error() implementation guards its own writes too, for a different cause. Stream operations there can fail: a stream can be closed, or open and refuse the write, and a report of a failure must not itself become a second failure.

ConsoleFrontController writes to stderr and falls back to log() only when that write fails. It tests what fwrite() returns, because a stream that refuses the write reports false rather than throwing.

RequestFrontController always logs, then attempts the response separately, so a failed log does not prevent the 500. FrankenFrontController logs and returns 1.

The directives bind run() alone. ConsoleFrontController and RequestFrontController throw InvalidArgumentException from __construct() when a stream argument is not a stream resource. Construction is outside them.

See the Front-Interop interface package for the full specification.