Search code examples
phpoopurlroutespathinfo

How to fix this router class to include 404 errors/pages?


I'm working on a simple router for php practice, it's already evolved quite a bit more but I'm posting the more simplistic version.

My router class check a given url vs the current server path and returns content if they match. This works fine but the problem is that the router runs 3 times because I'm calling the router get() method 3 times in my routes.php file.

If I for example want to return a 404 error when the route does not match it will return it 3 times. 1 time for each route not found. What is the best way to fix this?

As always your help is much appreciated.

Router class:

<?php
class Router {
    public $currentRoute = '/';
    public function __construct()
    {
        $this->getCurrentRoute();
    }
    public function getCurrentRoute()
    {
        if(isset($_SERVER['PATH_INFO'])) {
            $this->currentRoute = $_SERVER['PATH_INFO'];
        }
    }
    public function get($route, $content)
    {
        if($route == $this->currentRoute) {
            echo $content();
        }
    }
}

Routes file:

<?php

$router->get('/', function()
{
    return 'Index page';
});

$router->get('movies', function()
{
    return Cinematix\View::make('movies');
});

$router->get('users', function() 
{
    return 'The users collection page';
});

Solution

  • First be warned that your approach is not recommended. Looking up the classic MVC programming pattern is a good way to start.

    Read on if you really want to do it the way you started using anonymous callbacks.

    Router class:

    class Router {
        public $currentRoute = '/';
        private $routes;
    
        public function __construct($routes)
        {
            $this->routes = $routes;
            $this->getCurrentRoute();
        }
        public function getCurrentRoute()
        {
            if(isset($_SERVER['PATH_INFO'])) {
                $this->currentRoute = $_SERVER['PATH_INFO'];
            }
        }
        public function route()
        {
            $route = $this->currentRoute;
    
            if (!isset($this->routes[$route])) {
                $route = '/404';
            }
    
            if (is_callable($this->routes[$route])) 
            {
                echo $this->routes[$route]();  
            }    
        }
    }
    

    routes file:

    $routes = array(
        '/' => function()
        {
            return 'Index page';
        },
        '/movies' => function()
        {
            return 'Movies';
        },
        '/users' => function() 
        {
            return 'The users collection page';
        },
        '/404' => function() 
        {
            return '404';
        }
    );
    
    $router = new Router($routes);
    $router->route();