PHPackages                             jsl/router - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. jsl/router

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

jsl/router
==========

A router

0.2.7(6mo ago)11552MITPHPPHP &gt;=8.0

Since Feb 23Pushed 6mo ago1 watchersCompare

[ Source](https://github.com/jslphp/router)[ Packagist](https://packagist.org/packages/jsl/router)[ RSS](/packages/jsl-router/feed)WikiDiscussions develop Synced today

READMEChangelogDependenciesVersions (8)Used By (2)

Router
======

[](#router)

### Quick example

[](#quick-example)

```
// Load composers autoloader
require __DIR__ '/path/to/vendor/autoload.php';

// Import and instantiate the router
use Jsl\Router\Router;

$router = new Router;

$router->get('/some/path', function () {
    return 'Response for URL /some/path';
});

// Run the router and get the response from the callback
$response = $router->run();

echo $response;
// If the URL is /some/path, then you'll see "Response for URL /some/path"
```

### Adding routes

[](#adding-routes)

Different ways of adding routes

```
// Add a GET route
$router->get('/foo', function () {
    return 'This is the callback for GET /foo';
});

// Add a POST route
$router->post('/foo', function () {
    return 'This is the callback for POST /foo';
});

//...same for put(), delete()

// Allow any verb
$router->any('/foo', function () {
    return 'This is the callback for any verb on /foo';
});

// Add a route for some other verb (PATCH is just an example)
$router->addRoute('PATCH', '/foo', function () {
    return 'This is the callback for PATCH /foo';
});
```

### Adding routes using attributes

[](#adding-routes-using-attributes)

```
// Add attributes to the class

// Add optional group info, like a prefix for all routes in the class
#[JslRouteGroup(prefix: '/foo')]
class SomeClass
{
    // Add a route for this method
    #[JslRoute(
        method: 'GET',
        path: '/bar',
        name: 'someName'
    )]
    public function someMethod()
    {
        return 'Callback for route /foo/bar';
    }
}

// Pass the class name to the router
$router->addRoutesFromClassAttributes(SomeClass::class);

// Or pass a list of class names
$router->addRoutesFromClassAttributes([
    SomeClass::class,
    SomeOtherClass::class,
]);
```

### Callbacks

[](#callbacks)

Route callbacks comes in different shapes and sizes

```
// Closure
$route->get('/foo', function () { ... });

// Passing class name and method name - The router will instantiate the class when running the router
$router->get('/foo', ['Some\ClassName', 'someMethod']);

// Passing instance and method name
$router->get('/foo', [$somClass, 'someMethod']);

// ...you can use any callable as callback
```

### Route parameters

[](#route-parameters)

Add dynamic route parameters

```
// (:num) - Matches only numbers (uses regex: [\d]+)
$router->get('/foo/(:num)', function ($param) {
    return "This is a route param: {$param}";
});

// (:hex) - Matches only hexadecimal characters (uses regex: [a-fA-F0-9]+)
$router->get('/foo/(:hex)', function ($param) {
    return "This is a route param: {$param}";
});

// (:any) - Matches any characters (up to the next /) (uses regex: [^\/]+)
$router->get('/foo/(:any)', function ($param) {
    return "This is a route param: {$param}";
});

// (:all) - Matches everything (including /) (uses regex: .*)
$router->get('/foo/(:all)', function ($param) {
    return "This is a route param: {$param}";
});

// Make a dynamic paramter optional by adding ?
$router->get('/foo/(:num)?', function ($param = 123) {
    return "This is a route param: {$param} or 123 if no param was passed";
});
```

### Group routes

[](#group-routes)

```
// Add a prefix to all routes in the group
$router->group(['prefix' => '/foo'], function (Router $router) {
    // This will add a route for /foo/bar
    $router->get('/bar', function () { ... });

    // This will add a route for /foo/example
    $router->get('/example', function () { ... });
});

// Use dynamic parameters in the prefix, just like in the routes
$router->group(['prefix' => '/foo/(:num)'], function (Router $router) {
    // This will add a route for /foo/(:num)/bar
    $router->get('/bar', function () { ... });
})
```

### Named routes

[](#named-routes)

Instead of remembering all URLs and manually keep updating/syncing links, you can use named routes

```
// Add a route and give it a name
$router->get('/foo', function () { ... })->setName('something-foo');

// Get the route for a specific name
$path = $router->getNamedRoute('something-foo');
// Returns: /foo

// Add a route with dynamic parameters and give it a name
$router->get('/foo/(:num)', function () { ... })->setName('something-foo');

// Get the route for a specific name with dynamic parameters
// Pass the values for each dynamic route parameter as an array
$path = $router->getNamedRoute('something-foo', [123]);
// Returns: /foo/123
```

### Resolve a callback

[](#resolve-a-callback)

If you pass in a class name: `['ClassName', 'methodName']` or `'ClassName'` that has `__invoke()`, the class needs to be instantiated. The router will do that for you when you call `run()`, but if you want to have control of the instantiation (to inject dependencies through some IoC container for example), you can set your own custom class resolver.

```
// An example that does what the default resolver does
$router->setClassResolver(function (string $className): object {
    return new $className;
});
```

The argument to your function will always be a string, and the response must be a class instance.
The above is just a minimal (and quite useless) example. Your function can do what ever you want (like resolving it through a container) as long as you return a class instance.

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance66

Regular maintenance activity

Popularity13

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~276 days

Recently: every ~330 days

Total

6

Last Release

206d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/9977?v=4)[Justin S. Leitgeb](/maintainers/jsl)[@jsl](https://github.com/jsl)

---

Top Contributors

[![magnus-eriksson](https://avatars.githubusercontent.com/u/3640297?v=4)](https://github.com/magnus-eriksson "magnus-eriksson (20 commits)")

---

Tags

phprouter

### Embed Badge

![Health badge](/badges/jsl-router/health.svg)

```
[![Health](https://phpackages.com/badges/jsl-router/health.svg)](https://phpackages.com/packages/jsl-router)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
