Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Flight Laravel Package

mikecao/flight

Flight is a fast, simple, extensible micro-framework for PHP. It offers a lightweight routing core with a RESTful router, view rendering, and optional extendable components, making it a good fit for small apps and APIs that don't need a full-stack framework.

View on GitHub
Deep Wiki
Context7

Getting Started

Flight (flightphp/core) is a micro-framework, not a Laravel component — treat it as the thing you reach for when a Laravel app is overkill (a webhook receiver, an internal tool, a tiny JSON API, a queue-adjacent side service). It has no container magic, no facades beyond a static Flight class, and no ORM.

Minimal setup:

composer require flightphp/core
// public/index.php
require __DIR__ . '/../vendor/autoload.php';

Flight::route('GET /health', fn() => Flight::json(['ok' => true]));
Flight::route('GET /users/@id', function ($id) {
    Flight::render('users/show', ['id' => $id]);
});

Flight::start();

Where to look first:

  1. Flight::route() / Flight::start() — the entire request lifecycle lives here.
  2. Flight::set('flight.views.path', ...) and flight.views.extension — the only view config most projects touch.
  3. Flight::render($template, $data, $key) — PHP-file templates by default, rendered into $data[$key] for your layout.

Your first real use case is almost always rendering a template from a controller-ish closure. In v3.19.4 that path resolution gained an opt-in security boundary:

Flight::set('flight.views.path', __DIR__ . '/../views');
Flight::set('flight.views.restrict_to_path', true); // new in 3.19.4

Turn it on the day you create the project, not later — see Gotchas.

Implementation Patterns

Keep routing closures thin. Flight has no autowiring, so the idiomatic pattern is a small bootstrap.php that wires services into Flight::set() / Flight::register() and closures that pull them back out. Pair this with PSR-4 autoloading for your own classes; Flight deliberately gives you nothing here.

View rendering. Default engine is plain PHP:

Flight::set('flight.views.path', __DIR__ . '/../views');
Flight::set('flight.views.extension', '.phtml');

Flight::route('GET /orders/@id', function ($id) {
    Flight::render('orders/show', ['order' => fetch_order($id)], 'content');
});
// views/orders/show.phtml receives $order AND $content (nested render target)

Security boundary is a config flag, so make it part of your app skeleton. The v3.19.4 addition is best consumed as: set flight.views.restrict_to_path = true in your bootstrap alongside flight.views.path, and write an integration test that asserts a traversal attempt (Flight::render('../../composer.json')) fails. That test is your regression guard if the flag is ever dropped during a refactor.

Validate template names at the edge when they're user-influenced. If you do Flight::render("emails/$type") where $type comes from a query string, restrict_to_path is now a second line of defence — but an allowlist is still the first:

$allowed = ['welcome', 'reset', 'receipt'];
if (!in_array($type, $allowed, true)) { Flight::halt(404); }

Integration with a Laravel codebase. The realistic pattern is a sub-application: mount Flight behind a Laravel route or deploy it as a separate vhost sharing a database. Flight boots its own error handler and output buffering, so don't call Flight::start() inside a Laravel controller without ob_start() and careful teardown — you'll fight Laravel's middleware and whoops handler. Prefer a separate deployable, or a Laravel Route::any('/micro/{any?}')->where('any', '.*') passthrough only if you genuinely need URL continuity.

Testing. No test harness ships. Use PHPUnit with Flight::set('flight.engine', ...) overrides, or just boot the app in a subprocess and hit it with curl/HttpClient. For view tests, assert on rendered output of a known template rather than on Flight internals.

Gotchas and Tips

restrict_to_path is opt-in and defaults to off. This is the single most important thing about 3.19.4: existing apps are unaffected, which also means nothing is fixed until you flip the flag. Audit any app where template names are partially user-derived.

Enabling it can break legitimate layouts. If your skeletons share templates via absolute paths, symlinked directories, or a views/shared outside flight.views.path, those renders will now fail. Common escape hatches: keep everything under one views root, or resolve shared partials by absolute path through a path you explicitly add to the views path. Test render-heavy pages immediately after enabling.

Symlinks are the classic surprise. With restriction on, a views directory that is a symlink or that contains symlinked subdirectories may not resolve the way you expect depending on how the realpath comparison is done. If templates disappear, readlink -f your views path first.

Config keys are namespaced strings, no typo protection. Flight::set('flight.views.restrict_to_path', true) silently does nothing if misspelled — there's no schema. Keep a single config.php returning an array and loop it into Flight::set() so typos surface in one place.

render() vs view()->render() — pick one. Flight::render() echoes/assigns; Flight::view()->render($template, $data) returns a string. Mixing them inside a layout is a common source of double output.

Error handling differs from Laravel. Flight::halt() and Flight::error() replace exceptions-as-control-flow. Register Flight::map('error', ...) early, and remember Flight's default error page is verbose — set flight.debug to false in production or you'll leak stack traces.

Extension points worth knowing: Flight::map() to override built-ins (e.g. replace the view engine with Twig/Blade via Flight::register('view', ...)), Flight::before()/Flight::after() for cross-cutting concerns, and Flight::register() for a poor-man's container. If you find yourself building more than two of these, that's the signal to use Laravel instead.

Version pinning. Flight is pre-1.0-style in its 3.x line with frequent point releases; pin with ^3.19.4 and read the changelog before bumping — there is no deprecation policy equivalent to Laravel's.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo