I have been writing a very slim MVC framework to drive a small personal website. It's nothing intricate, just mostly for fun and a learning experience.
Specifically, this is the initial part of the MVC and just the entry point. I don't want to develop all this logic for the models and views if my dispatcher is not going to work right in a production site. Again, this is just the entry of the project and handles requests to load the controllers via the URL. This is not the entire MVC project.
When I am looking at other frameworks out there, they seem quite complex in their handling of the routing and controller dispatching, and my final code is just a fraction of the size.
I have the server redirect all requests back to index.php using an .htaccess file or via a Nginx config file. I have tried both.
I use the index.php file as the entry point (this is the relevant part):
/* using "Example Implementation" of the PSR-0 standards supporting both '\' and '_' namespace seperations
* https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
* using file_exists to deal with otherwise unhandled errors
*/
function autoload($className) {
$className = ltrim($className, '\\');
$fileName = '';
$namespace = '';
if($lastNsPos = strripos($className, '\\')) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace('\\', DS, $namespace) . DS;
}
$fileName .= str_replace('_', DS, $className) . '.php';
$fileName = ROOT . DS . $fileName;
if(file_exists($fileName)) {
require($fileName);
}
}
$test = new framework\core\Router();
Router.php:
<?php
namespace framework\core {
class Router {
function __construct() {
//get the raw url
$urlRaw = $_SERVER['REQUEST_URI'];
//do the route :)
$this->route($urlRaw);
}
private function route($urlRaw) {
//do our best to split the url at the most obvious parts (/, ?, $, =)
$urlRawParts = preg_split('/[\/?&=]+/', $urlRaw, -1, PREG_SPLIT_NO_EMPTY);
//do a simple sanitization on the parts (allow alphanumeric and dash while stripping common web extensions)
$urlRawParts = preg_replace('/[^A-Za-z0-9\-]|\bhtm\b|\bphp\b|\bhtml\b/', '', $urlRawParts);
//set our controller and action or use defaults
$controller = ((!empty($urlRawParts[0])) ? $urlRawParts[0] : 'Index');
$action = ((!empty($urlRawParts[1])) ? $urlRawParts[1] : 'index');
$arguments = ((count($urlRawParts) > 2) ? array_slice($urlRawParts, 2) : array());
$this->dispatch($controller, $action, $arguments);
}
private function dispatch($controller, $action, $arguments) {
//format the call to our class
$controller = 'application\\controllers\\' . ucfirst($controller) . 'Controller';
//load our class or show the appropriate error page
$controller = ((class_exists($controller) ? new $controller() : new Error('404')));
//use the default class method unless a valid one exists
$method = ((method_exists($controller, $action)) ? $action : 'index');
//call our class method
call_user_func_array(array($controller, $method), $arguments);
}
}
}
?>
This works for any URL that I throw at it and will always default to a known file (Error.php which is just a simplified controller and view in one).
Am I missing anything huge here? Is my logic way off or not complete? Is this utilization slow or wasteful on resources? I'm just looking for a general idea on if I am on the right track.
<head>
part of your server response, for example? Otherwise, it is fair for personal site, why not. \$\endgroup\$