Search code examples
phpurl-routingfile-exists

PHP file_exists returning false


I'm trying to write my own little MVC framework for my projects, something I can just drop in and get up and running quickly, mostly for learning purposes. Every request gets routed through index.php which has this code:

<?php

// Run application
require 'application/app.php';
$app = new App();
$app->run();

This is my application class:

<?php

class App {

    public function run() {
        // Determine request path
        $path = $_SERVER['REQUEST_URI'];

        // Load routes
        require_once 'routes.php';

        // Match this request to a route
        if(isset(Routes::$routes[$path])) {

        } else {
            // Use default route
            $controller = Routes::$routes['/'][0];
            $action = Routes::$routes['/'][1];
        }

        // Check if controller exists
        if(file_exists('controllers/' . $controller . '.php')) {
            // Include and instantiate controller
            require_once 'controllers/' . $controller . '.php';
            $controller = new $controller . 'Controller';

            // Run method for this route
            if(method_exists($controller, $action)) {
                return $controller->$action();
            } else {
                die('Method ' . $action . ' missing in controller ' . $controller);
            }
        } else {
            die('Controller ' . $controller . 'Controller missing');
        }
    }

}

and this is my routes file:

<?php

class Routes {

    public static $routes = array(
        '/' => array('Pages', 'home')
    );

}

When I try loading the root directory (/) I get this:

Controller PagesController missing

For some reason the file_exists function can't see my controller. This is my directory structure:

/application
    /controllers
        Pages.php
    /models
    /views
    app.php
    routes.php

So by using if(file_exists('controllers/' . $controller . '.php')) from app.php, it should be able to find controllers/Pages.php, but it can't.

Anyone know how I can fix this?


Solution

  • You are using relative path's for your includes. As your application grows, it will become a nightmare.

    I suggest you

    • write a autoloader class, that deals with including files. Use some mapping mechanism that translates namespaces / class names into path's.
    • use absolute paths. See the adjusted code below.

    Example:

    // Run application
    define('ROOT', dirname(__FILE__) );
    require ROOT . '/application/app.php';
    $app = new App();
    $app->run();
    

    And later:

    // Check if controller exists
    if(file_exists(ROOT . '/application/controllers/' . $controller . '.php')) {
        // Include and instantiate controller
        require_once ROOT. '/application/controllers/' . $controller . '.php';
        $controller = new $controller . 'Controller';