I recently started developing my first serious project in PHP, a MVC completely build by myself, which is quite a challenge, when being new to OOP.
So the main struggle of the whole project has, and is, my router. It's really important, so I want to have a... great?... router, that just works - but without compromising functionality.
Creating a router in itself wasn't really a challenge (Might be because I do it a wrong way), but after having made a basic router that did the job, I realized the 2 main problems. GET functionality and folders.
The challenge is pretty URLs AND being able to load controllers from specific folder (or subfolders of it), executing specific method and passing in GET values.
I tried, and it works. But it's really just a mess:
class router {
/**
* Contains the path of the controller to be loaded.
* This will be extended if the "bit" does not exist as a file.
* This makes it possible to put controllers into folder.
*
*/
public static $path = null;
/**
* Contains the name of the file to be loaded.
* This is also used when instantiating the controller, as the name of the class inside the file, and the name of the file, should be identical.
*
*/
public static $file = null;
/**
* Contains the name of the method to be run inside the controller
*
*/
public static $method = null;
/**
* This function is run at the index file, and should only be run once. Running it twice serves no purpose, and will just result in errors.
* It fetches the controller, and runs specified method inside the controller - or shows error 'notfound'.
* If more parameters are specified than just the path of the controller, the controllers name and the method to be run, it will pass theese to the
* get helper, if loaded.
*
* The get helper must be autoloaded though, because the get parameters are passed to the get helper before running the content of the controller.
*/
public static function dispatch() {
// Remove Simple MVC's location from request
$request = str_replace(config::get('routes/path'), '', $_SERVER['REQUEST_URI']);
if(!$request) {
$request = config::get('routes/defaultController');
}
// Split request into array
$path = explode('/', $request);
// Go trough array
foreach($path as $bit) {
// Check whether the method already has been set
if(self::$method == null) {
// Check whether to file to load already has been set
if(self::$file == null) {
// Check if a file exists at the already defined 'path' with the name of bit
if(file_exists('app/controllers/' . self::$path . $bit . '.php')) {
// Set file name
self::$file = $bit;
// Require in the file
require('app/controllers/' . self::$path . self::$file . '.php');
// Instantiate controller
$controller = new self::$file();
// If file does not exist
} else {
// Add the bit to the path
self::$path .= $bit . '/';
}
// If file already has been loaded
} else {
// Check whether 'bit' method exists in the controller
if(method_exists($controller, $bit)) {
// Set method to 'bit'
self::$method = $bit;
}
}
// If method already has been defined, check whether the 'get' helper has been loaded
} elseif(helper::isLoaded('get')) {
// Push 'bit' to the 'get' helper
array_push(get::$values, $bit);
}
}
// Check whether the controller has been instantiated
if(isset($controller)) {
// Check whether the method has been set
if(self::$method == null) {
// If method has not been set, run defaultFunction
$controller->defaultFunction();
// If method has been set
} else {
// Run defined method
$method = self::$method;
$controller->$method();
}
// If controller is not set
} else {
// Show 'notfound' error
error::show('notfound');
}
}
}
The dispatch()
method is simply run at the index file, which the .htaccess file just redirects all requests to.
The request is then split into an array, which a foreach
then go through and first of it tries to find a file with the name of 'bit', if it does not exist it add the 'bit' to the path from the controllers folder. This makes subfolders possible. When it has the file, it continues until it has a method. When a method is defined, all remaining 'bits' get passed to an array in the 'GET' helper.
But this being such a mess, I'm hoping for opinions and advice.