Search by

sulcompany / router

sulcompany

A lightweight, dependency-free PHP router with dynamic routes, middleware, route groups, contexts, and built-in error handling.

Package info

github.com/sulcompany/router

pkg:composer/sulcompany/router

Statistics

Installs: 8

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v3.0.0 2026-10-10 15:50 UTC

This package is auto-updated.

Last update: 2026-10-10 15:57:58 UTC


README

A lightweight, dependency-free PHP router with dynamic routes, middleware, route groups, contexts, and built-in error handling.

PHP Version License PSR-11 Latest Version Total Downloads

πŸ‡ΊπŸ‡Έ English | πŸ‡΅πŸ‡Ή PortuguΓͺs

πŸ“– Overview

SulCompany Router is a mini routing framework for PHP 8.1+. It is not PSR-7, not FastRoute. It is a simple, direct, opinionated alternative for developers who want:

  • HTTP routing
  • Middleware pipeline
  • Route groups with prefix, name, and context
  • Configurable error handling
  • An integrated PSR-11 container (optional)
  • Zero dependencies besides psr/container

It was built to be predictable, readable, and extensible β€” without the weight of a full framework.

✨ Features

  • βœ… REST routes (GET, POST, PUT, PATCH, DELETE)
  • βœ… Dynamic parameters (/user/{id})
  • βœ… Wildcard parameters (/files/{path*})
  • βœ… Named routes and URL generation
  • βœ… Nested groups (prefix + name + context + middleware)
  • βœ… Contexts (admin, ecommerce, ...) for differentiated error views
  • βœ… before / after middleware pipeline
  • βœ… PSR-11 container with autowiring
  • βœ… Route cache (via var_export)
  • βœ… Error handling via ErrorHandlerInterface
  • βœ… Automatic JSON / AJAX detection
  • βœ… No heavy dependencies

πŸ“‹ Requirements

Requirement Version
PHP ^8.1
Composer ^2.0
psr/container ^2.0 (installed automatically)

πŸš€ Installation

composer require sulcompany/router

⚑ Quick Start

1. Create public/index.php

<?php

declare(strict_types=1);

ob_start();

use SulCompany\Router\Dispatcher;
use SulCompany\Router\Router;

require __DIR__ . '/../vendor/autoload.php';

$router = new Router('https://mysite.com');

$router->get('/', function ($request, $response) {
    return $response->html('<h1>Hello, world!</h1>');
}, name: 'home');

$router->get('/user/{id}', [UserController::class, 'show'], name: 'user.show');

$dispatcher = new Dispatcher($router);
$dispatcher->dispatch();

while (ob_get_level() > 0) {
    ob_end_flush();
}

2. Test it

  • GET / β†’ returns HTML
  • GET /user/42 β†’ executes UserController::show('42')

Done. πŸŽ‰

🧠 The Basics

Routes

$router->get('/about', [SiteController::class, 'about'], name: 'site.about');
$router->get('/user/{id}', [UserController::class, 'show'], name: 'user.show');
$router->get('/files/{path*}', [FileController::class, 'download'], name: 'files.download');

πŸ“– Full route documentation β†’

Groups

$router->group('/admin', name: 'admin', context: 'admin', middleware: [AuthAdmin::class], callback: function ($r) {
    $r->get('/users', [UserController::class, 'index'], name: 'users.index');
});

πŸ“– Full group documentation β†’

Middleware

class AuthMiddleware
{
    public function before(Request $request, Response $response): bool
    {
        if (!auth()->check()) {
            $response->redirect('/login');
            return false;
        }
        return true;
    }
}

πŸ“– Full middleware documentation β†’

Controllers

$router->get('/user/{id}', [UserController::class, 'show'], name: 'user.show');

πŸ“– Full controller documentation β†’

Request

$request->method();
$request->path();
$request->header('accept');
$request->get('page');
$request->post('name');
$request->json('field');
$request->expectsJson();

πŸ“– Full request documentation β†’

Response

return $response->html('<h1>Hello</h1>');
return $response->json(['ok' => true]);
return $response->redirect('/login');

πŸ“– Full response documentation β†’

Error Handling

final class AppErrorHandler implements ErrorHandlerInterface
{
    public function handle(int $status, Request $request, Response $response): Response
    {
        if ($request->expectsJson()) {
            return $response->json(['error' => true], $status);
        }
        return $response->html("<h1>Error {$status}</h1>", $status);
    }
}

πŸ“– Full error handling documentation β†’

Container (DI)

$container = new Container();
$container->singleton(PDO::class, fn() => new PDO('mysql:...'));
$container->bind(UserRepository::class, fn($c) => new UserRepository($c->get(PDO::class)));

πŸ“– Full container documentation β†’

Route Cache

$router->enableCache(__DIR__ . '/cache/routes.php');
if (!$router->loadCache()) {
    $router->get('/', ...);
    $router->compile();
    $router->cacheCompiledRoutes();
}

πŸ“– Full cache documentation β†’

URL Generation

$router->urlFor('user.show', ['id' => 42]);
// β†’ https://mysite.com/user/42

πŸ“– Full URL generation documentation β†’

πŸ“š Documentation

Document Description
Routes HTTP methods, dynamic params, wildcards
Groups Prefix, name, context, middleware, nesting
Middleware Before/after, types, order
Controllers Closures, classes, DI
Request All request methods
Response All response builders
Error Handling Contract, default, custom
Container PSR-11, bind, singleton, autowiring
Cache Route compilation and caching
URL Generation Named routes and urlFor()

πŸ“– πŸ‡΅πŸ‡Ή DocumentaΓ§Γ£o em PortuguΓͺs β†’

⚠️ Important Notes

Output Buffering

ob_start();           // at the top

// ... your code ...

while (ob_get_level() > 0) {
    ob_end_flush();   // at the end
}

Without this, your pages may render blank with content-length: 0.

Exceptions

The Router does not catch exceptions. Use try/catch in your index.php.

Not PSR-7

Request and Response are mutable and minimalist.

PSR-11 Container

The Container class implements Psr\Container\ContainerInterface.

🧩 Compatibility

PHP Supported
8.1 βœ…
8.2 βœ…
8.3 βœ…
8.4 βœ… (not yet tested)
7.x ❌

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Commit your changes
  4. Push to the branch
  5. Open a Pull Request

πŸ› Reporting Issues

Open an issue with PHP version, Router version, and a minimal reproduction.

πŸ‘₯ Credits

  • Francisco Dulo β€” author
  • Sul Company Lda β€” maintainer
  • Contributors β€” everyone who helped

πŸ“„ License

MIT β€” see LICENSE.

SulCompany Router β€” made with πŸ–€ in Angola.