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

Proton Laravel Package

alexbilbie/proton

Proton is a lightweight PHP micro-framework by Alex Bilbie for building small web applications and APIs. It provides simple routing and a minimal, extensible structure, making it a handy Composer-installable starting point for tiny projects.

View on GitHub
Deep Wiki
Context7

Getting Started

Proton is a micro framework in the truest sense: a thin Application object that wires together Symfony's HttpFoundation, FastRoute, a Pimple-style DI container, and StackPHP middleware. There is no CLI, no generator, no config DSL — the framework is a handful of classes you can read end-to-end in under an hour. That is the first thing to do.

Minimal bootstrap:

composer require alexbilbie/proton
// public/index.php
require __DIR__ . '/../vendor/autoload.php';

$app = new Proton\Application();

$app->get('/', function ($request, $response) {
    $response->setContent('Hello world');
    return $response;
});

$app->run();

Point nginx/Apache at public/index.php as the single front controller. run() builds a Request from globals, dispatches through your middleware stack, executes the matched handler, and send()s the Response.

Where to look first, in order:

  1. src/Proton/Application.php — routing methods (get, post, put, delete, any), register(), addMiddleware(), run().
  2. Whatever the routing dispatch does with FastRoute — this dictates placeholder syntax (/users/{id}) and how parameters reach you ($request->getAttribute('id')).
  3. The container class — how services are registered and resolved, since that is your only injection mechanism.

First real use case: a small JSON API. One route, one closure, return a Symfony\Component\HttpFoundation\JsonResponse (or $response->headers->set('Content-Type', 'application/json') plus setContent(json_encode(...))). That gets you from zero to a working endpoint in about ten lines, which is exactly the niche this package fills.

Implementation Patterns

Routing. Verb methods take a pattern and a callable. Handlers receive (Request $request, Response $response) and must return a Response. Named placeholders are read from request attributes rather than method arguments, so controllers stay decoupled from the router. Group route definitions into routes/api.php files that accept $app and are required from the bootstrap — the framework gives you no structure, so impose your own early.

Controllers as invokables. Closures stop scaling at roughly five routes. Move each handler into an invokable class (__invoke(Request $request, Response $response): Response), register it in the container, and pass the service name or a [$app->container, 'name']-style callable to the route. This is where you get testability and constructor injection for free.

Container registration is your service layer. Register the database connection, Twig, Monolog, and any repositories as lazy closures. Because resolution is lazy, a closure that captures $app is fine as long as it doesn't touch services at registration time. Override services in tests by re-registering the same key before dispatching.

Middleware is StackPHP. $app->addMiddleware(new SomeMiddleware) wraps the kernel; signature is (Request $request, callable $next) returning a Response, with $next($request) continuing the chain. Order matters — the first-added middleware is the outermost layer. Use it for:

  • an error-handling middleware that catches Throwable and converts it to a 500 JSON/HTML response (do this first, before anything else can throw);
  • CORS headers;
  • authentication/session bootstrapping;
  • request logging with timing.

Keep middleware single-purpose; there is no priority system, only insertion order.

Config. Pass an array to the Application constructor (or set container parameters). Read environment from getenv() in the bootstrap and pick config/dev.php vs config/prod.php. Never hardcode credentials in route files.

Testing. Because everything is HttpFoundation, you can skip HTTP entirely: build a Request::create('/users/1', 'GET') and invoke the kernel's handle() (or call the app's dispatch method) directly inside PHPUnit. Assert on status code and body. This is the cheapest win available — do it before writing a single integration test through a web server.

Splitting the app. A common shape: bootstrap.php returns a configured $app; public/index.php requires it and calls run(); tests/ requires the same bootstrap and calls handle() instead. One wiring path, two entry points.

Gotchas and Tips

  • It is unmaintained. Last activity is years old, the code targets PHP 5.x/7.0-era tooling, and dependencies (StackPHP in particular, superseded by PSR-15) receive no security patches. Expect friction on PHP 8: pin PHP 7.4, or fork and patch. If this is greenfield, Slim 4 or a Symfony micro-kernel gives you the same footprint with active maintenance. Choose Proton deliberately — for a small internal tool, a legacy service, or to learn how frameworks are assembled.
  • You must return a Response. Echoing, print, or falling off the end of a handler yields a blank or fatal response with no useful error. Every branch of every handler needs an explicit return.
  • Middleware order is the whole configuration. Error handling that is added after auth will not catch auth exceptions. Register the catch-all wrapper first.
  • FastRoute caching is opt-in and manual. If you enable the cached dispatcher, route changes need a cache clear; in dev, keep it disabled or you will spend an hour debugging a route you already added.
  • Route registration is eager, dispatch is lazy. Registering routes after run() obviously does nothing; registering services after they are first resolved also does nothing, because Pimple caches instances once created.
  • No CSRF, no session handling, no validation, no ORM. Anything you need, you add as middleware or a container service. Budget for it — a "micro framework" project still needs these, they just aren't pre-decided for you.
  • Debugging: var_dump() inside a handler writes before output buffering kicks in and can corrupt the response. Prefer error_log(), or a Monolog-backed logger pulled from the container. The Xdebug stack trace from an uncaught exception is more informative than anything the framework prints.
  • Extension points are few but sufficient: subclass Application to add your own route helpers or default middleware, decorate the container, and swap the dispatcher. Do not patch files in vendor/ — wrap or subclass instead, or you lose the ability to update at all (which, given the project's state, may be the only update you ever get).
  • Dependency hygiene: because nothing upstream moves, run composer audit and composer outdated yourself on a schedule. Treat every transitive dependency as yours to maintain.
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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log