PHPackages                             jimbojsb/rapid - 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. [Framework](/categories/framework)
4. /
5. jimbojsb/rapid

ActiveLibrary[Framework](/categories/framework)

jimbojsb/rapid
==============

A PHP Middleware dispatcher / router inspired by Express.js

24PHP

Since Aug 17Pushed 9y ago3 watchersCompare

[ Source](https://github.com/jimbojsb/rapid)[ Packagist](https://packagist.org/packages/jimbojsb/rapid)[ RSS](/packages/jimbojsb-rapid/feed)WikiDiscussions master Synced 3w ago

READMEChangelogDependenciesVersions (1)Used By (0)

Rapid
=====

[](#rapid)

Rapid is a PSR-7 / middleware dispatcher inpsired by Express.js. Rapid's only external dependency is the PSR-7 `Psr\HttpMessage` interfaces. Rapid requires PHP 7.0 or above.

Installation
------------

[](#installation)

```
$ composer require offers/rapid

```

Create your application
-----------------------

[](#create-your-application)

```
$application = new Rapid\Application();
// add middlewares here
$application->run();
```

Define middlewares
------------------

[](#define-middlewares)

Rapid accepts several values to represent a middleware. Any place Rapid expects a middleware as an argument, any of the following methods may be used

#### Passing an instance

[](#passing-an-instance)

If passing an instance, your instance should implement `Rapid\MiddlewareInterface`This method is useful if you need to do custom instantiation of an instance for dependency injection.

```
$application->use(new ExampleMiddleware());
```

#### Passing a class name

[](#passing-a-class-name)

If your middleware doesn't need any custom instantiation, you can pass a class name instead. Your class will not be instantiated unless the system actually needs to use that given middleware.

```
$application->use(ExampleMiddleware::class);
```

#### Passing a closure

[](#passing-a-closure)

A closure that with a `Rapid\MiddlewareInterface` compatible signature may also be used. Type hinting the arguments is optional but recommended.

```
$application->use(function(ServerRequestInterface $request, ResponseInterface $response, callable $next) {

});
```

#### Using a middleware factory

[](#using-a-middleware-factory)

`Rapid\Application` optionall accepts a `callable` that should be used to produce middlewares when a classname is specified. This callable can be responsible for wiring and dependency injection as you see fit. The factory should be a `callable` that takes one argument (a class name) and returns a properly wired middleware of that class. An interface, `Radpid\MiddlewareFactoryInterface` is provided for convenience but not required.

```
$application->setMiddlewareFactory($factory);
```

Composing and routing middleware
--------------------------------

[](#composing-and-routing-middleware)

Middleware is evaluated top-to-bottom as defined in your application bootstrapping. Middleware may be applied to every request or applied using traditional routing methods that are evaluated against an instance of `\Psr\HttpMessage\ServerRequestInterface`. All middlewares will be checked against each request, and multiple matches are permitted and encouraged.

**Apply a middleware to every request**

```
$application = new Rapid\Application();
$application->use(new ExampleMiddleware());
```

**Match middlewares based on method and simple path**

```
$application->get("/test", TestMiddleware::class);
```

**Match middlewares on any method and simple path**

```
$application->all("/test", TestMiddleware::class);
```

**Match middlewares on any method and simple path**

```
$application->all("/test", TestMiddleware::class);
```

**Apply a group of middlewares to a given path**

```
$application->get("/test", [TestMiddleware::class, ExampleMiddleware::class]);
```

**Apply a middleware to more than one method on the same route**

```
$application->route(["POST", "PUT"], "/test", TestMiddleware::class);
```

**Apply different middlewares to different methods on the same route**

```
$application->get("/test", GetMiddleware::class);
$application->post("/test", PostMiddleware::class);
```

Routing
-------

[](#routing)

Rapid includes a built-in router / url matcher.

URLs that start with `/` and contain no special operators as noted below are treated as an exact string match to the request path. In the following exmaple, GetMiddleware will be invoked if the path of the request uri is exactly `/test`

```
$application->get("/test", GetMiddleware::class);
```

URLs that start with a `/` and contain a `{}` are matched with a system-generated regular expression. Path segments surrounded with `{}` are treated as variables and the values of those segments will be set as attributes on the request object. In the following example, a request path of `/test/myslug` results in a request attribute of `slug` being set to `myslug`.

```
$application->get("/test/{slug}", GetMiddleware::class);
```

At the end of any given path prefix, a special marker `{?}` may be added that treats the remainder of any path match as a Rails-style key-value route. In the following example, a request path of `/test/param1/value1/param2/value2` results in a request attributes of `param1` and `param2` being set to `value1` and `value2` respectively. *Note: This route matches on 0 or more options, so it will also match for `/test`*

```
$application->get("/test{?}", GetMiddleware::class);
```

Path specifications that are surrounded by backticks are treated as regular expressions and are passed to `preg_match()` as written. If the regeular expression matches, the `$matches` array is set as a request attribute.

```
$application->get("`/test.*?`", GetMiddleware::class);
```

**Using a custom route matcher**

Rapid supports using a custom `callable` for route matching. This may be useful in scenarios where a database needs to be consulted to see if a route matches or not. The callable should take one argument, a `\Psr\HttpMessage\RequestInterface` and return either `false` (no match) or a `\Psr\HttpMessage\RequestInterface` which may be the instance it was passed, or a mutated instance that it has decorated with attributes as necessary. An interface, `Rapid\RouteMatcherInterface` is provided for convenience but is not required.

```
$application->get(function($request) {
    if ($request->getUri()->getPath = "/complex-logic") {
        return $request;
    }
    return false;
}, DataBackedMiddleware::class);
```

Using middleware pipes
----------------------

[](#using-middleware-pipes)

The convenience methods on the `Rapid\Application` object are actually proxies to the underlying container object `Rapid\MiddlewarePipe`. It is possible to use middleware pipes directly for even more flexibility and reusability at bootstrap time.

Create a new middleware pipe with a single middleware and use it:

```
$pipe = new \Radid\MiddlewarePipe(RunAlwaysMiddleware::class);
$application->use($pipe);
```

Create a new middleware pipe with multiple middlewares

```
$pipe = new \Radid\MiddlewarePipe([RunAlwaysMiddleware::class, AnotherMiddleware::class]);
$application->use($pipe);
```

Add a middleware to an existing pipe

```
$pipe = new \Radid\MiddlewarePipe();
$myMiddleware = new MyMiddleware();
$pipe->pipe($myMiddleware);
```

Middleware pipes are also fully routing-aware. The pipe method will also accept a closure. Inside the closure, you may use the same syntax as the convenience methods on the application object.

```
$pipe = new \Radid\MiddlewarePipe();
$pipe->pipe(function() {
    $this->use(MiddlewareOne::class);
    $this->get('/prefix', PrefixMiddleware::class);
});
```

A more concrete example using pipes for organizational purposes. Middleware pipes can be subsituted wherever a middleware would be used.

```
$publicPipe = new \Radid\MiddlewarePipe();
$publicPipe->pipe(function() {
   $this->get("/", HomepageMiddleware::class);
   $this->get("/login", LoginMiddleware::class);
});
$application->use($publicPipe);

$privateDirectoryPipe = (new Rapid\MiddlewarePipe())->pipe(function() {
    $this->get("/user", (new MiddlewarePipe)->pipe(function() {
        $this->use(AuthMiddleware::class);
        $this->get("/user/dashboard", DashBoardMiddleware::class);
        $this->get("/user/settings", SettingsMiddleware::class);
    }));
});
$application->use($privateDirectoryPipe);
```

Handling errors
---------------

[](#handling-errors)

Rapid error handlers are also defined as middlewares. Error middlewares have a slightly different signature, and are described in their own `Rapid\Middleware\ErrorMiddlewareInterface`. The first argument to an error handling middleware is a `Throwable`.

Rapid catches `Throwable` in it's dispatch cycle, so PHP 7.x `Error` throws are caught as well and can be processed by these middlewares. Before invoking the first error middleware, Rapid will set the `Throwable` as an attribute on the `$request` and change the `$response` status code to 404 or 500 if applicable. Rapid includes 2 special `Exceptions` for routing issues: `Rapid\Exception\MethodNotAllowedException` and `Rapid\Exception\NoRouteMatchException`.

```
$application->use(ErrorMiddleware::class);
```

Extending the base application
------------------------------

[](#extending-the-base-application)

`Rapid\Application` is in itself, a very simple class. It provides an empty `init()` method that will be called for bootstrapping purposes. The default constructor is left purposely without arguments under the assumption that it will likely be overloaded. It is assumed that a user will want to extend the base application class and implement all of the middleware bootstrapping in the `init()` method, and overload the constructor with arguments like a dependency injection container to be used in `init()`.

###  Health Score

20

—

LowBetter than 13% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity41

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.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/107836?v=4)[Josh Butts](/maintainers/jimbojsb)[@jimbojsb](https://github.com/jimbojsb)

---

Top Contributors

[![jimbojsb](https://avatars.githubusercontent.com/u/107836?v=4)](https://github.com/jimbojsb "jimbojsb (20 commits)")

### Embed Badge

![Health badge](/badges/jimbojsb-rapid/health.svg)

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

###  Alternatives

[laravel/socialite

Laravel wrapper around OAuth 1 &amp; OAuth 2 libraries.

5.7k104.3M829](/packages/laravel-socialite)[laravel/dusk

Laravel Dusk provides simple end-to-end testing and browser automation.

1.9k38.6M289](/packages/laravel-dusk)[pinguo/php-msf

Pinguo Micro Service Framework For PHP

1.7k4.2k](/packages/pinguo-php-msf)[nineinchnick/edatatables

Grid widget for the Yii Framework, wrapper for the DataTables jQuery plugin

173.2k](/packages/nineinchnick-edatatables)[link-cloud/fast-hyperf

LinkCloud Fast Hyperf

241.2k1](/packages/link-cloud-fast-hyperf)

PHPackages © 2026

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