In house we have been building our own MVC framework. One of the things that was important in the project was to not have to add routes manually but instead have a standard and let the index automatically handle routing based on that standard.
We want to access the URL /home/login
- /home is the controller
- /login is the method in the home controller
System hierarchy
- Home
- Controller
- Home.php
- Controller
Here is that index. Is there anything we could be doing differently or better?
We are using PHP 8.1 and NGINX with php-fpm
<?php
session_start();
// contains stuff like $engine which is etheir
// nginx or apache and the composer autoloader
require_once __DIR__.'/config.php';
if(isset($argv)){
// this block is so we can call php index.php --uri="/controller/action"
$options = getopt('',array('uri::'));
$url = explode('/', ltrim($options['uri'],'/'));
}else{
// Determine this engine so we know how to parse url
if($engine == 'nginx'){
$url = isset($_SERVER['REQUEST_URI']) ? explode('/', ltrim($_SERVER['REQUEST_URI'],'/')) : '/';
}else if($engine == 'apache'){
$url = isset($_SERVER['PATH_INFO']) ? explode('/', ltrim($_SERVER['PATH_INFO'],'/')) : '/';
}
}
// Check if controller/action is provided if not load homepage
if ($url == '/' || empty($url[0])){
require_once("{$rootPath}Home/Controller/Home.php");
$controller = new Home();
$view = $controller->index();
$controller->init();
if($controller->data != null){
extract($controller->data, EXTR_PREFIX_SAME, 'wddx');
}
$cssFiles = $controller->cssFiles;
$jsFiles = $controller->jsFiles;
$useLocalJquery = $controller->useLocalJquery;
$viewPath = "{$rootPath}Home/View/{$view}.php";
if(file_exists($viewPath)){
require_once("{$rootPath}Template/View/template.php");
}
}else{
//The first element should be a controller
$requestedController = ucfirst($url[0]);
// If a second part is added in the URI,
// it should be a method
$requestedAction = isset($url[1]) && $url[1] != '' ? ucfirst($url[1]) : 'Index';
// The remain parts are considered as
// arguments of the method
$requestedParams = array_slice($url, 2);
// Check if controller exists.
$ctrlPath = "{$rootPath}{$requestedController}/Controller/{$requestedController}.php";
if (file_exists($ctrlPath)){
$view = null;
require_once($ctrlPath);
$controllerObj = new $requestedController();
//Check that action exist or return 404
if(!method_exists($controllerObj,$requestedAction)){
header('HTTP/1.1 404 Not Found');
require_once("{$rootPath}Template/View/404.php");
}
if($requestedAction != ''){
$view = $controllerObj->$requestedAction($requestedParams);
}else{
// If no action is specified we default to loading the index
$view = $controllerObj->index($requestedParams);
}
$controllerObj->init();
if($controllerObj->data != null){
extract($controllerObj->data, EXTR_PREFIX_SAME, 'wddx');
}
$cssFiles = $controllerObj->cssFiles;
$jsFiles = $controllerObj->jsFiles;
$useLocalJquery = $controllerObj->useLocalJquery;
if($view != null){
// Store view path
$viewPath = "{$rootPath}{$requestedController}/View/{$view}.php";
// Check if view uses template
if($controllerObj->useTemplate){
$templatePath = "{$rootPath}Template/View/{$controllerObj->template}.php";
if(file_exists($templatePath)){
require_once("{$rootPath}Template/View/{$controllerObj->template}.php");
}
}else{
// If the view does not use the template then we just load the view
if(file_exists($viewPath)){
require_once($viewPath);
}
}
}
}else{
header('HTTP/1.1 404 Not Found');
require_once("{$rootPath}Template/View/404.php");
}
}
require_once
. \$\endgroup\$extract
in global scope. \$\endgroup\$