Simple PHP Routing for Invoice Management System

For the Invoice Management System application, we need to have routing of requests. Routing will help us to implement pages independently from each other and be rendered via a handler such as a PHP custom function or even better – An Action Controller PHP class. In this post, we are going to implement a simple router functionality so we can handle HTTP GET requests and render different information based on the page we are currently in.

The Request Class

The Request class provides a set of methods that are used in the Router class for identifying a callback function. With the help of the parse_url() function we can get an associated array of elements from a current URL. The URL is located in the $_SERVER[‘REQUEST_URI’] global array.

<?php declare(strict_types=1);

namespace Invoice;

class Request
{
    private array $server;

    public function __construct()
    {
        $this->server = $_SERVER;
    }

    public function getServer(string $name): mixed
    {
        return $this->server[$name] ?? null;
    }

    public function getUri(): array
    {
        return parse_url($this->getServer('REQUEST_URI'));
    }

    public function getPath(): string
    {
        $uri = $this->getUri();
        return $uri['path'];
    }
}

The Router Class

The Router class is responsible for finding or dispatching an incoming HTTP request and returning a callback function that is triggered in the App::run() method. For simplicity, we are going to hard-code the list of routes inside the dispatch() method. Later, we are going to move the list of routes to a separate config file.

<?php declare(strict_types=1);

namespace Invoice;

class Router
{
    public function dispatch(Request $request): mixed
    {
        $path = $request->getPath();

        $routes = [
            '/' => function () {
                echo 'Home Page';
            },
            '/invoices' => function () {
                echo 'Invoices';
            },
            '/settings' => function () {
                echo 'Settings';
            }
        ];

        return $routes[$path] ?? null;
    }
}

Putting Everything Together

The App::run() method is responsible for instantiating the Request and Router classes. The Request object is passed as an argument of the Router::dispatch() method.


<?php declare(strict_types=1);

namespace Invoice;

class App
{
    public function run(): void
    {
        $router = new Router();

        $request = new Request();
        $handler = $router->dispatch($request);

        if ($handler) {
            $handler();
        }
    }
}

The dispatch() method returns a handler function that is later executed inside the run() method. As a result, we render different content based on the request path information provided by the Request::getPath() method.

Service Container

Both Request and Router classes may also be instantiated via the Service Container class that is responsible for managing dependencies. As for a simple PHP routing implementation, we aren’t going to add a service container. A separate post, however, will cover the service container topic.

And Finally…

You may watch a video tutorial with an additional explanation of the simple PHP router implementation. This video is a part of videos dedicated to the creation of the Invoice Management System.

All source code from this post can be found on GitHub.


Posted

in

by

Tags:

Comments

Leave a Reply