PHPackages                             alexoliverwd/basic-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. [HTTP &amp; Networking](/categories/http)
4. /
5. alexoliverwd/basic-router

ActiveLibrary[HTTP &amp; Networking](/categories/http)

alexoliverwd/basic-router
=========================

A minimalistic yet powerful PHP class designed to handle routing in web applications.

0.6.4(3mo ago)0408↓62.5%[2 issues](https://github.com/aoliverwd/basic-router/issues)MITPHPPHP &gt;=8.4CI passing

Since Dec 8Pushed 3mo ago1 watchersCompare

[ Source](https://github.com/aoliverwd/basic-router)[ Packagist](https://packagist.org/packages/alexoliverwd/basic-router)[ RSS](/packages/alexoliverwd-basic-router/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (10)Dependencies (4)Versions (23)Used By (0)

[![PHPUnit](https://github.com/aoliverwd/basic-router/actions/workflows/ci.yml/badge.svg)](https://github.com/aoliverwd/basic-router/actions/workflows/ci.yml/badge.svg) [![Latest Stable Version](https://camo.githubusercontent.com/b88e0f2c4cba2c2875a5c8ae1c10086552ff876319026a582af1724186361623/68747470733a2f2f706f7365722e707567782e6f72672f616c65786f6c6976657277642f62617369632d726f757465722f76)](//packagist.org/packages/alexoliverwd/basic-router) [![License](https://camo.githubusercontent.com/3b0ad23aba1dc791a91ea22074ad90d9ec51be9581dfbd23652188e1b0a482b2/68747470733a2f2f706f7365722e707567782e6f72672f616c65786f6c6976657277642f62617369632d726f757465722f6c6963656e7365)](//packagist.org/packages/alexoliverwd/basic-router)

Router
======

[](#router)

This application is a minimalistic yet powerful PHP class designed to handle routing in web applications. It's a dependency-free solution that offers a straightforward approach to mapping HTTP requests to functions or methods, with full support for registering routes and middleware using PHP Attributes.

Important

To prevent XSS attacks, use the built-in `getParameter` method when retrieving values from query parameters.

For more information on using the `getParameter` method, see the [XSS Prevention](#xss-prevention) section.

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

[](#installation)

Preferred installation is via Composer:

```
composer require alexoliverwd/basic-router
```

Usage
-----

[](#usage)

When a request comes in to the application, the Router instance will examine the request method (GET, POST, PUT, DELETE) and the requested URL. If a matching route is found, the associated callback function will be executed.

### Attribute-Based Controller Routing

[](#attribute-based-controller-routing)

Attributes provide a modern, native way to declare route metadata directly in your code. This approach is now recommended for defining routes, while conventional methods will remain supported for compatibility.

```
use AOWD\Router;
use AOWD\Attributes\Route;
use AOWD\Attributes\GET;
use AOWD\Attributes\PUT;
use AOWD\Attributes\POST;
use AOWD\Attributes\DELETE;

class myRoutes {
    #[Route('/hello-world', 'get')]
    public function homeGet(): void
    {
        echo "GET - Hello World";
    }

    #[Route('/hello-world/segment/[0-9]+', 'get')]
    public function homeGetSegment(Router $router): void
    {
        echo $router->getSegment(1);
    }

    #[Route('/hello-world', 'post')]
    public function homePost(): void
    {
        echo "POST - Hello World";
    }

    #[Route('/users/{userId}/orders/{orderId}', 'get')]
    public function getUserOrder(Router $router): void
    {
        $user_id = $router->URLAttribute("userId");
        $order_id = $router->URLAttribute("orderId");
        echo "User: $user_id Order: $order_id";
    }

    // CRUD Attributes

    #[GET('/crud-hello-world')]
    public function crudHomeGet(): void
    {
        echo "CRUD GET - Hello World";
    }

    #[PUT('/crud-hello-world')]
    public function crudHomePut(): void
    {
        echo "CRUD PUT - Hello World";
    }

    #[POST('/crud-hello-world')]
    public function crudHomePost(): void
    {
        echo "CRUD POST - Hello World";
    }

    #[DELETE('/crud-hello-world')]
    public function crudHomeDelete(): void
    {
        echo "CRUD DELETE - Hello World";
    }
}

$router = new Router();
$router->registerRouteController(new myRoutes());
$router->run();
```

### Route Interface

[](#route-interface)

Classes that implement the route interface have access to the `prepend_path` variable. This variable allows all routes registered within the class to be automatically prefixed with a common path.

This is useful when all routes in a class must follow a shared convention, such as starting with `/api/`. If the convention needs to change in the future, it can be updated in one place at the top level rather than modifying every individual route definition within the class.

```
use AOWD\Interfaces\Route as RouteInterface;
use AOWD\Attributes\Route;
use AOWD\Attributes\GET;
use AOWD\Router;

class routeWithPrependedSlug implements RouteInterface
{
    public string $prepend_path;
    public function __construct() {
        $this->prepend_path = $_ENV['PAGE_WITH_SLUG'];
    }

    #[Route('-env', 'get')]
    public function pageWithEnv(): void
    {
        echo "Page with ENV";
    }

    #[GET('-crud-hello-world')]
    public function homeCrudGET(): void
    {
        echo "CRUD GET - Hello World";
    }
}

$router = new Router();
$router->registerRouteController(new routeWithPrependedSlug());
$router->run();
```

### Registering Multiple Controllers

[](#registering-multiple-controllers)

In the below example, multiple controllers can be registered with the router in a single call using the `registerRouteController()` method. Each controller class defines its own set of routes through PHP attributes, the router will automatically scan and map them.

```
use AOWD\Router;
use AOWD\Attributes\Route;

class getRoutes {
    #[Route('/hello-world', 'get')]
    public function homeGet(): void
    {
        echo "GET - Hello World";
    }

    #[Route('/hello-world/segment/[0-9]+', 'get')]
    public function homeGetSegment(Router $router): void
    {
        echo $router->getSegment(1);
    }
}

class postRoutes {
    #[Route('/hello-world', 'post')]
    public function homePost(): void
    {
        echo "POST - Hello World";
    }
}

$router = new Router();
$router->registerRouteController(new getRoutes(), new postRoutes());
$router->run();
```

### Conventional Method

[](#conventional-method)

```
use AOWD\Router;

$router = new Router();

$router->register('GET', '/', function () {
    echo 'get';
});

$router->register("get", "/second/segment/[0-9]+", function () use ($router) {
    echo $router->getSegment(1);
});

// CRUD Helper Methods

$router->get('/', function () {
    echo 'get';
});

$router->put('/', function () {
    echo 'put';
});

$router->post('/', function () {
    echo 'post';
});

$router->delete('/', function () {
    echo 'delete';
});

$router->run();
```

In this example, if a GET request is made to the root URL (/), the function function () { echo 'get'; } will be called, and the string "get" will be output.

### Registering an endpoint

[](#registering-an-endpoint)

The `register` method registers a new route in the routing system.

#### Parameters

[](#parameters)

1. **Method:** The HTTP method (e.g., GET, POST, PUT, DELETE).
2. **Route:** The URL pattern for the route.
3. **Callback:** The callable function or method to be executed when the route is matched.

#### Return Value:

[](#return-value)

- true: If the route is successfully registered.
- false: If the route already exists for the specified method.

### Executing registered routes

[](#executing-registered-routes)

The `run()` method is the core of the routing system. It's responsible for:

1. Parsing the Request: Extracts the requested URL path and HTTP method from the server environment.
2. Matching Routes: Compares the parsed request against registered routes to find a matching route.
3. Executing Callback: If a match is found, the associated callback function is executed.
4. Handling 404 Errors: If no match is found, the registered 404 error handler is invoked.

### Unregistering an endpoint

[](#unregistering-an-endpoint)

```
$router->unregister('get', '/get');
```

This method unregisters a previously registered route from the routing system.

#### Parameters

[](#parameters-1)

1. **Method:** The HTTP method (e.g., GET, POST, PUT, DELETE) in lowercase.
2. **Route:** The URL pattern of the route to be unregistered.

#### Return Value:

[](#return-value-1)

- true: If the route is successfully unregistered.
- false: If the route doesn't exist or couldn't be unregistered.

### Handling 404 errors

[](#handling-404-errors)

```
$router->register404(function () {
    echo '404 error';
});
```

The `register404` method registers a callback function to be executed when a 404 Not Found error occurs. This allows you to customize the error handling behavior for your application.

#### Parameters

[](#parameters-2)

1. **Callback:** A callable function or method that will be invoked when a 404 error is encountered. This callback can be used to generate custom error messages, redirect to a specific page, or perform other error handling actions.

### Returning values from URL segments

[](#returning-values-from-url-segments)

The `getSegment` method returns a single segment value from a URI. The returned value may be an integer or a string, depending on how the segment is referenced. The method accepts either an integer index or a string key.

#### Using an integer index

[](#using-an-integer-index)

When an integer is provided, it represents the position of the segment in the URI, counted from left to right, starting at `0`.

For example, given the URI: `segment/standard/123`

- `getSegment(0)` returns `segment`
- `getSegment(1)` returns `standard`
- `getSegment(2)` returns `123`

Negative integers are also supported and count segments from right to left:

- `getSegment(-1)` returns `123`
- `getSegment(-2)` returns `standard`

#### Using a string key

[](#using-a-string-key)

When a string is provided, `getSegment` returns the value associated with a URI template attribute.

For example, given the URI template: `segment/standard/{id}`Calling: `getSegment('id')`returns: `123`

```
use AOWD\Router;

$router = new Router();

$router->register("get", "/segment/standard/{id}", function () use ($router) {
    echo $router->getSegment('id');
});

$router->run();
```

For more information about URI template attributes, see the next section.

### Returning values from URL attributes

[](#returning-values-from-url-attributes)

When defining a route that includes attribute placeholders (e.g., `/users/{userId}/orders/{orderId}`), you can easily retrieve those values by using the URLAttribute method.

```
#[Route('/users/{userId}/orders/{orderId}', 'get')]
public function URLAttributesTest(Router $router): void
{
    $user_id = $router->URLAttribute("userId");
    $order_id = $router->URLAttribute("orderId");
    echo "User: $user_id Order: $order_id";
}

#[Route('/segment/attribute/{id}', 'get')]
public function homeGetSegmentIdViaAttribute(Router $router): void
{
	echo $router->getSegment('id');
}
```

#### Parameters

[](#parameters-3)

1. **Reference ID *(string)*** — The name of the URL attribute to retrieve (e.g., `userId`).
2. **Fallback *(string|int, optional)*** — A value to return if the requested attribute is not found.

Note

Attribute names may only contain alphabetic characters (A–Z, a–z), hyphens, and underscores (i.e., a-z, A-Z, -, \_).

---

XSS Prevention
==============

[](#xss-prevention)

Get safe values from query string parameters
--------------------------------------------

[](#get-safe-values-from-query-string-parameters)

To mitigate the risk of cross-site scripting (XSS) attacks, use the built-in `getParameter` method. This method retrieves a sanitised scalar value from a query string parameter, helping prevent the injection of malicious scripts.

```
use AOWD\Router;

$router = new Router();

// URL: localhost://xss?q=alert('XSS')
$router->register("get", "/xss", function () use ($router) {
	// Will display &lt;script&gt;alert(&#039;XSS&#039;)&lt;/script&gt;
    echo $router->getParameter('q');
});

$router->run();
```

---

Middleware
==========

[](#middleware)

Middleware in this routing API provides a way to intercept and process requests before they reach your route handler. This allows you to implement reusable logic such as **authentication, logging, CORS handling, rate limiting, or response modification** without duplicating code inside your route controllers.

Middleware classes must implement or extend the `AOWD\Interfaces\Middleware` interface, which requires a `handle()` method. When a route is matched, any attached middleware will be executed in the order they are defined.

Usage
-----

[](#usage-1)

### 1. Creating a Middleware

[](#1-creating-a-middleware)

To create a middleware, implement the `MiddlewareInterface` and define the `handle()` method.

```
use AOWD\Interfaces\Middleware as MiddlewareInterface;

class helloWorld implements MiddlewareInterface
{
    public function handle(): void
    {
        echo "Hello World ";
    }
}
```

This simple example outputs `Hello World` before the route logic executes.

### 2. Attaching Middleware to a Route

[](#2-attaching-middleware-to-a-route)

Middleware can be attached to a route using the `#[Middleware()]` attribute.

```
use AOWD\Attributes\Route;
use AOWD\Attributes\Middleware;

class myRoutes {
    #[Route('/hello-world-middleware', 'get')]
    #[Middleware(helloWorld::class)]
    public function homeGetMiddleware(): void
    {
        echo "GET";
    }
}
```

In this example:

- A `GET` request to `/hello-world-middleware` will first run the `helloWorld` middleware.
- The middleware prints `"Hello World "`.
- Then the route handler executes and prints `"GET"`.
- The final response is:

```
Hello World GET
```

### 3. Registering Routes and Running the Router

[](#3-registering-routes-and-running-the-router)

After defining routes and middleware, register your route controller with the `Router` and start it:

```
use AOWD\Router;

$router = new Router();
$router->registerRouteController(new myRoutes());
$router->run();
```

Full Example
------------

[](#full-example)

Here’s everything combined into a single working example:

```
use AOWD\Router;
use AOWD\Attributes\Route;
use AOWD\Attributes\Middleware;
use AOWD\Interfaces\Middleware as MiddlewareInterface;

class helloWorld implements MiddlewareInterface
{
    public function handle(): void
    {
        echo "Hello World ";
    }
}

class myRoutes {
    #[Route('/hello-world-middleware', 'get')]
    #[Middleware(helloWorld::class)]
    public function homeGetMiddleware(): void
    {
        echo "GET";
    }
}

$router = new Router();
$router->registerRouteController(new myRoutes());
$router->run();
```

###  Health Score

42

—

FairBetter than 89% of packages

Maintenance81

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity56

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 ~25 days

Recently: every ~20 days

Total

19

Last Release

103d ago

PHP version history (2 changes)0.1.0PHP &gt;=8.3

0.3.0PHP &gt;=8.4

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/2101296?v=4)[Alex Oliver](/maintainers/alexoliverwd)[@alexoliverwd](https://github.com/alexoliverwd)

---

Top Contributors

[![aoliverwd](https://avatars.githubusercontent.com/u/37518812?v=4)](https://github.com/aoliverwd "aoliverwd (38 commits)")

---

Tags

httproutingcrud

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[aplus/app

Aplus Framework App Project

5981.6M1](/packages/aplus-app)[miladrahimi/phprouter

A powerful, lightweight, and very fast HTTP URL router for PHP projects.

20633.5k2](/packages/miladrahimi-phprouter)[wilaak/radix-router

High-performance radix tree based HTTP request router

615.0k5](/packages/wilaak-radix-router)[elementaryframework/water-pipe

URL routing framework and requests/responses handler for PHP

254.9k4](/packages/elementaryframework-water-pipe)

PHPackages © 2026

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