SkillAgentSearch skills...

Phprouter

PhpRouter is a full-featured yet very fast HTTP URL router for PHP projects

Install / Use

/learn @miladrahimi/Phprouter

README

Latest Stable Version Total Downloads Build codecov Scrutinizer Code Quality License

PhpRouter

PhpRouter is a full-featured yet very fast HTTP URL router for PHP projects.

Some of the provided features:

  • Route parameters
  • Predefined route parameter patterns
  • Middleware
  • Closure and class controllers/middleware
  • Route groups (by prefix, middleware, and domain)
  • Route naming (and generating route by name)
  • PSR-7 requests and responses
  • Views (simple PHP/HTML views)
  • Multiple (sub)domains (using regex patterns)
  • Custom HTTP methods
  • Integrated with an IoC Container (PhpContainer)
  • Method and constructor auto-injection of Request, Route, Url, etc

The current version requires PHP v8.0 or newer versions.

Contents

Versions

  • v5.x.x (Current, Supported)
  • v4.x.x
  • v3.x.x
  • v2.x.x
  • v1.x.x

Documentation

Installation

Install Composer and run following command in your project's root directory:

composer require miladrahimi/phprouter "5.*"

Configuration

First of all, you need to configure your webserver to handle all the HTTP requests with a single PHP file like the index.php file. Here you can see sample configurations for NGINX and Apache HTTP Server.

  • NGINX configuration sample:

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
  • Apache .htaccess sample:

    <IfModule mod_rewrite.c>
        <IfModule mod_negotiation.c>
            Options -MultiViews
        </IfModule>
    
        RewriteEngine On
    
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule ^(.*)/$ /$1 [L,R=301]
    
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^ index.php [L]
    </IfModule>
    

Getting Started

It's so easy to work with PhpRouter! Just take a look at the following example.

  • JSON API Example:

    use MiladRahimi\PhpRouter\Router;
    use Laminas\Diactoros\Response\JsonResponse;
    
    $router = Router::create();
    
    $router->get('/', function () {
        return new JsonResponse(['message' => 'ok']);
    });
    
    $router->dispatch();
    
  • View Example:

    use MiladRahimi\PhpRouter\Router;
    use MiladRahimi\PhpRouter\View\View
    
    $router = Router::create();
    $router->setupView('/../views');
    
    $router->get('/', function (View $view) {
        return $view->make('profile', ['user' => 'Jack']);
    });
    
    $router->dispatch();
    

HTTP Methods

The following example illustrates how to declare different routes for different HTTP methods.

use MiladRahimi\PhpRouter\Router;

$router = Router::create();

$router->get('/', function () { /* ... */ });
$router->post('/', function () { /* ... */ });
$router->put('/', function () { /* ... */ });
$router->patch('/', function () { /* ... */ });
$router->delete('/', function () { /* ... */ });

$router->dispatch();

You can use the define() method for other HTTP methods like this example:

use MiladRahimi\PhpRouter\Router;

$router = Router::create();

$router->define('GET', '/', function () { /* ... */ });
$router->define('OPTIONS', '/', function () { /* ... */ });
$router->define('CUSTOM', '/', function () { /* ... */ });

$router->dispatch();

If you don't care about HTTP verbs, you can use the any() method.

use MiladRahimi\PhpRouter\Router;

$router = Router::create();

$router->any('/', function () {
    return 'This is Home! No matter what the HTTP method is!';
});

$router->dispatch();

Controllers

Closure Controllers

use MiladRahimi\PhpRouter\Router;

$router = Router::create();

$router->get('/', function () {
    return 'This is a closure controller!';
});

$router->dispatch();

Class Method Controllers

use MiladRahimi\PhpRouter\Router;

class UsersController
{
    function index()
    {
        return 'Class: UsersController & Method: index';
    }

    function handle()
    {
        return 'Class UsersController.';
    }
}

$router = Router::create();

// Controller: Class=UsersController Method=index()
$router->get('/method', [UsersController::class, 'index']);

// Controller: Class=UsersController Method=handle()
$router->get('/class', UsersController::class);

$router->dispatch();

Route Parameters

A URL might have one or more variable parts like product IDs on a shopping website. We call it a route parameter. You can catch them by controller method arguments like the example below.

use MiladRahimi\PhpRouter\Router;

$router = Router::create();

// Required parameter
$router->get('/post/{id}', function ($id) {
    return "The content of post $id";
});

// Optional parameter
$router->get('/welcome/{name?}', function ($name = null) {
    return 'Welcome ' . ($name ?: 'Dear User');
});

// Optional parameter, Optional / (Slash)!
$router->get('/profile/?{user?}', function ($user = null) {
    return ($user ?: 'Your') . ' profile';
});

// Optional parameter with default value
$router->get('/roles/{role?}', function ($role = 'guest') {
    return "Your role is $role";
});

// Multiple parameters
$router->get('/post/{pid}/comment/{cid}', function ($pid, $cid) {
    return "The comment $cid of the post $pid";
});

$router->dispatch();

Route Parameter Patterns

In default, route parameters can have any value, but you can define regex patterns to limit them.

use MiladRahimi\PhpRouter\Router;

$router = Router::create();

// "id" must be numeric
$router->pattern('id', '[0-9]+');

$router->get('/post/{id}', function (int $id) { /* ... */ });

$router->dispatch();

Requests and Responses

PhpRouter uses laminas-diactoros (formerly known as zend-diactoros) package (v2) to provide PSR-7 request and response objects to your controllers and middleware.

Requests

You can catch the request object in your controllers like this example:

use MiladRahimi\PhpRouter\Router;
use Laminas\Diactoros\ServerRequest;
use Laminas\Diactoros\Response\JsonResponse;

$router = Router::create();

$router->get('/', function (ServerRequest $request) {
    $method  = $request->getMethod();
    $uriPath = $request->getUri()->getPath();
    $headers = $request->getHeaders();
    $queryParameters = $request->getQueryParams();
    $bodyContents    = $request->getBody()->getContents();
    // ...
});

$router->dispatch();

Responses

The example below illustrates the built-in responses.

use Laminas\Diactoros\Response\RedirectResponse;
use MiladRahimi\PhpRouter\Router;
use Laminas\Diactoros\Response\EmptyResponse;
use Laminas\Diactoros\Response\HtmlResponse;
use Laminas\Diactoros\Response\JsonResponse;
use Laminas\Diactoros\Response\TextResponse;

$router = Router::create();

$router->get('/html/1', function () {
    return '<html>This is an HTML response</html>';
});
$router->get('/html/2', function () {
    return new HtmlResponse('<html>This is also an HTML response</html>', 200);
});
$router->get('/json', function () {
    return new JsonResponse(['error' => 'Unauthorized!'], 401);
});
$router->get('/text', function () {
    return new TextResponse('This is a plain text...');
});
$router->get('/empty', function () {
    return new EmptyResponse(204);
});
$router->get('/redirect', function () {
    return new RedirectResponse('https://miladrahimi.com');
});

$router->dispatch();

Views

You might need to create a classic-style server-side rendered (SSR) website that uses views. PhpRouter has a simple feature for working with PHP/HTML views. Look at the following example.

use MiladRahimi\PhpRouter\Router;
use MiladRahimi\PhpRouter\View\View

$router = Router::create();

// Setup view feature and set the directory of view files
$router->setupView(__DIR__ . '/../views');

$router->get('/profile', function (View $view) {
    // It looks for a view with path: __DIR__/../views/profile.phtml
    return $view->make('profile', ['user' => 'Jack']);
});

$router->get('/blog/post', function (View $view) {
    // It looks for a view with path: __DIR__/../views/blog/post.phtml
    return $view->make('blog.post', ['post' => $post]);
});

$router->dispatch();

There is also some points:

  • View files must have the ".phtml" extension (e.g. profile.phtml).
  • You can separate directories with . (e.g. blog.post for blog/post.phtml).

View files are pure PHP or mixe

Related Skills

View on GitHub
GitHub Stars208
CategoryDevelopment
Updated1mo ago
Forks21

Languages

PHP

Security Score

100/100

Audited on Feb 22, 2026

No findings