Max Pe
Max Pe

Reputation: 1

PHP: Simple Routing class, question how to add mutiple routes

I try to work with a simple Router class (learning basics before a framework, but I think I got something wrong with the example router I used. Below is a very small router class I got from a colleague and I tried to integrate it into my code to substitute previous uses where I just used echo before (commented out part of the code). both loginController showLoggedInUser() and registerController index() are just used to render an html template.

Both $router->add() would work if I use it just to add a single route, however my router does not save multiple routes in the array because it seems every route will be saved under the key '/' and in case I provide mutiple routes it seems my previous routes are simply overwritten. So I guess I would need to adjust the Router class. How can I fix this?

PHP 7.4 used

Router.php

<?php
declare(strict_types=1);

class Router
{
    private array $route;

    public function add(string $url, callable $method): void
    {
        $this->route[$url] = $method;
    }

    public function run()
    {

        $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
        if(!array_key_exists($path, $this->route))

        {
            exit();
        }
        return call_user_func($this->route[$path]);
    }
}

index.php

<?php
declare(strict_types=1);

require __DIR__ . '/../vendor/autoload.php';

session_start();

$router = new Router();

$mysqliConnection = new MysqliConnection();
$session = new SessionService();

$loginController = new Login($mysqliConnection);
$router->add('/', [$loginController, 'showLoggedInUser']);
//echo $loginController->showLoggedInUser();


$registerController = new Register($mysqliConnection);
$router->add('/', [$registerController, 'index']);
//echo $registerController->index();


echo $router->run();

Upvotes: 0

Views: 634

Answers (1)

Nigel Ren
Nigel Ren

Reputation: 57121

Not sure of the overall principle of having two routes with the same name, but you could achieve this using a list of callables for each route.

I've made some changes (including the callable passed for each route) to show the principle, but you should get the idea...

class Router
{
    private array $route;

    public function add(string $url, callable $method): void
    {
        $this->route[$url][] = $method;
    }

    public function run()
    {

        $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
        if(!array_key_exists($path, $this->route))

        {
            exit();
        }
        foreach ( $this->route[$path] as $paths )   {
            $paths();
        }
        // Not sure what to return in this case.
        // return call_user_func($this->route[$path]);
    }
}

$router = new Router();

// $mysqliConnection = new MysqliConnection();
// $session = new SessionService();

// $loginController = new Login($mysqliConnection);
$router->add('/', function () { echo "login"; } );


// $registerController = new Register($mysqliConnection);
$router->add('/', function () { echo "Register"; });


echo $router->run();

I would instead recommend having separate url's, /login and /register so that they can be called separately.

Upvotes: 1

Related Questions