Modelo Vista Controlador en PHP
Descripción
Un ejemplo completo de cómo implementar el Modelo Vista Controlador (MVC) con PHP.
Otros artículos
El main
Para los que no lo sepáis, main es la función principal en C y C++, o método en Java, que se llama al iniciar una aplicación. El punto de entrada se puede modificar para que sea otro y no esta función/método, pero por defecto es éste.
En el caso que nos concierne, el main o punto de entrada de la aplicación será un script nada original: index.php. Pero antes de verlo os muestro el ".htaccess" de la web pues es importante saber cómo se manejan las peticiones mediante el ModRewrite.
Options -Multiviews
RewriteEngine On
RewriteBase /
RewriteRule ^css/(.*)$ - [L]
RewriteRule ^img/(.*)$ - [L]
RewriteRule ^([0-9a-z_-]+)/?$ index.php?section=$1 [L,QSA]
RewriteRule ^([0-9a-z_-]+)/([^/]+)/?$ index.php?section=$1¶m=$2 [L,QSA]
php_value blitz.tag_open "{"
php_value blitz.tag_close "}"
La opción Multiviews es para permitir que si un directorio solicitado no existe, se busque en su anterior ruta el archivo con el nombre del directorio indicado. Por ejemplo, si vamoa a miweb.com/admin/inicio, con esta opción se buscaría el archivo inicio (con la extensión según el orden de la configuración de apache, por ejemplo primero php, luego html...) en el directorio admin.
Después tenemos la activación del motor de rescritura, y la definición de ruta base para la rescritura como "/", o sea el directorio raíz de la web. Y le siguen las reglas de rescritura: las dos primeras son para evitar que se intente rescribir las peticiones a los directorios css e img, que deben ignorarse pues ahí están los archivos de imagen y de estilo; y por último tenemos una regla para cuando se reciba un parámetro y otro para cuando se reciban dos. Según la primera regla, si vamos a restless-souls.net/news se traduciría a index.php?section=news, y según la segunda al ir a restless-souls.net/news/noticia-inexistente se ejecutaría el script index.php?section=news¶m=noticia-inexistente. El típico sistema de rescritura de URL. Recordad que tenéis que tener activado el ModRewrite en el apache, y que si usáis otro servidor web tendréis que usar el método que éste os proporcione.
Ahora pasamos a ver el archivo index.php:
//Script principal que cargará todas las páginas según la sección
session_start();
//Variable para controlar el código de error de la aplicación
$_GET['error'] = 0;
//El título de la sección y la sección a incluir (la clase)
$sectionInfo = array('title' => 'Inicio', 'class' => '');
//Requerimos la clase de la aplicación
require_once('classes/RSWebApp.php');
$app = new RSWebApp;
//Cargamos la configuración
$app->loadConfig('config/main.php');
//Iniciamos la aplicación
try{
$app->init();
//Si no se ha recibido la sección cargaremos el índice
if (empty($_GET['section'])){
$_GET['section'] = 'news';
}
try{
$sectionInfo = $app->getSection($_GET['section']);
} catch (Exception $e){
$sectionInfo = array('title' => 'Error', 'class' => 'ControllerError');
//Debemos tener un código de error que almacenamos para mostrarlo
$_GET['error'] = $e->getCode();
}
//Intentamos cargar la cabeza de la página
try{
$app->showHeader($sectionInfo['title']);
} catch (Exception $e){
$sectionInfo = array('title' => 'Error', 'class' => 'ControllerError');
$_GET['error'] = $e->getCode();
}
//Intentamos cargar el menú principal
try{
$app->showMainMenu($sectionInfo['title']);
} catch (Exception $e){
$sectionInfo = array('title' => 'Error', 'class' => 'ControllerError');
$_GET['error'] = $e->getCode();
}
//Intentamos cargar la sección
try{
$app->showBody($sectionInfo['class'], $_GET, $_POST, $_COOKIE, $_FILES, $_SESSION, $_SERVER);
} catch (Exception $e){
//El método showBody de la aplicación no lanza excepciones...
echo "[{$e->getCode()}] {$e->getMessage()}";
}
//Intentamos cargar el menú lateral
try{
$app->showSideMenu();
} catch (Exception $e){
$app->showError("Side menu error [{$e->getCode()}]");
}
//Intentamos cargar el pie de la página
try{
$app->showFooter($_SERVER['SCRIPT_URI']);
} catch (Exception $e){
$app->showError("Footer error [{$e->getCode()}]");
}
//Terminamos la aplicación
$app->terminate();
} catch (Exception $e){
echo "[{$e->getCode()}] {$e->getMessage()}";
}
Es tan fácil como esto. Se inicia la sesión, un par de inicializaciones de variables, se instancia la aplicación, y a cargar las partes de la web. Se podría haber prescindido de todos los "try catch" anidados que hay y dejar el primero, pero yo prefiero que si falla una sola parte de la web se siga intentando con la siguiente.
Y esto es todo. Personalmente me parece que es un método muy práctico de realizar una aplicación con el MVC, y si bien tiene algunos puntos que hacen que no sea de uso global (como el uso de Blitz) es casi homogénea en su totalidad; y si programáis vuestros propias extensiones de modelo, vuestra propia clase para la aplicación, y modificáis el index.php para adecuarlo a vuestra clase para la aplicación, tendréis una implementación de MVC acorde a vuestras necesidades. Y como decía en el inicio del artículo, la idea es que sepáis implementar el MVC por vuestra propia cuenta, sin depender de frameworks ni de aplicaciones de terceros; de modo que es espero que se os haya abierto un poco la mente con este artículo.
Versión para imprimir