Escrito por: neTo
El Modelo
La ‘M’ de los sistemas MVC se refiere al modelo, es responsable de ejecutar consultas a la base de datos (u otra fuente externa como pueden ser archivos xml, csv, etc.) y proveer los datos al controlador. Nosotros debe cargar el modelo apropiado dependiendo de la solicitud de nuestro cliente, algunas personas prefieren no utilizar una clase modelo y utilizar en el controlador una librería que haga la abstracción de la BDD, como por ejemplo AdoDB, sin embargo el modelo también puede hacer uso de esta librería o utilizar las funciones nativas de php directamente. Todo depende del tamaño de la aplicación y lo práctico que resulte en la solución que propongamos
Algo que debemos hacer es agregar el código necesario para inicializar una conexión con la base de datos, y añadirlo a nuestra pagina inicial (index). Existe varias librerías de abstracción de la BDD disponibles, pero PHP5 ya viene con una gran librería PDO, entonces es posible que no necesitemos alguna más.
Ahora, colocamos el siguiente código en el archivo index (luego de incluir el archivo de inicialización):
# Conexión con la BDD
$db = new PDO('mysql:host=localhost;dbname=demo', '[usuario]', '[clave]');
$registry->set ('db', $db);
En el ejemplo anterior primero creamos una nueva instancia de la libreria PDO, y nos conectamos a nuestra base de datos MySQL. Posteriormente hace global la conexión mediante nuestra clase Registry.
La parte del modelo de nuestro sistema, esta terminada, por lo que vamos a pasar con con la siguiente parte: codificar el controlador.
Codificar el controlador también significa que nosotros debemos codificar la clase Router. Una clase Router es responsable de cargar correctamente el controlador, basada en las solicitudes (la variable $router pasada a través de la URL). Entonces vamos a codificar la clase Router primero.
La clase Router
Nuestra clase Router deberá analizar la solicitud del cliente y cargar el comando correcto. El primer paso es crear el esqueleto básico de la clase Router:
Class Router
{
private $registry;
private $path;
private $args = array();
function __construct($registry) {
$this->registry = $registry;
}
}
Y agregamos las siguiente líneas al archive index.php:
# Carga el router
$router = new Router($registry);
$registry->set ('router', $router);
Ahora hemos añadido la clase Router a nuestro sistema MVC, pero esta no hace nada aún, entonces debemos agregar varios métodos a nuestra clase.
El primer metodo que debemos agregar es setPath(), el cual es utilizado para definir el directorio donde se almacenan todos nuestros controladores. El metodo setPath() es similar al siguiente y require ser agregado a la clase Router:
function setPath($path)
{
$path = trim($path, '/\\');
$path .= DIRSEP;
if (is_dir($path) == false) {
throw new Exception ('Path Invalido: `' . $path . '`');
}
$this->path = $path;
}
Nota: Si su sistema no tiene la constante DIRSEP, prueben con DIRECTORY_SEPARATOR
Luego, agregamos la siguiente línea en el archivo index.php:
$router->setPath (site_path . 'controllers');
Ahora nosotros ya tenemos definido el path a nuestros controladores, entonces podemos escribir el método responsable de cargar el controlador correcto. Este método es llamado delegate(). Una primera versión de este método puede ser como sigue:
function delegate()
{
// Obtiene el controlador
$this->getController($file, $controller, $action, $args);
Como pueden ver, hace uso de otro método, getController() para obtener el controlador. Este método sería algo así:
private function getController(&$file, &$controller, &$action, &$args)
{
$route = (empty($_GET['route'])) ? '' : $_GET['route'];
if (empty($route)) { $route = 'index'; }
// Separa las partes
$route = trim($route, '/\\');
$parts = explode('/', $route);
// Busca el controlador correcto
$cmd_path = $this->path;
foreach ($parts as $part) {
$fullpath = $cmd_path . $part;
// Existe un directorio con el path completo?
if (is_dir($fullpath)) {
$cmd_path .= $part . DIRSEP;
array_shift($parts);
continue;
}
// Busca el archivo
if (is_file($fullpath . '.php')) {
$controller = $part;
array_shift($parts);
break;
}
}
if (empty($controller)) { $controller = 'index'; };
// Obtiene la accion
$action = array_shift($parts);
if (empty($action)) { $action = 'index'; }
$file = $cmd_path . $controller . '.php';
$args = $parts;
}
Veamos un poco el funcionamiento de este método. Primero obtiene el valor de la variable $route y procede a separarla en partes, utilizando la función explode(). Si la solicitud es ‘miembro/ver’ esto debería dividirlo en un arreglo: array(‘miembro’, ‘ver’).
Podemos utilizar el loop foreach para recorrer cada parte y primero chequear si cada parte es un directorio. Si lo es, lo agregamos en el filepath y nos movemos a la siguiente parte. Esto permite poner al controlador en subdirectorios, y utilizar jerarquía en los controladores. Si una parte no es un directorio pero es un archivo, almacenamos esto en la variable $controller, y salimos del loop por que hemos encontrado el controlador que queríamos.
Luego del loop nos aseguramos que el controlador ha sido encontrado, y si no existe un controlador ponemos por omisión a uno llamado ‘index’.
Procedemos a obtener la acción que deseamos ejecutar. El controlador es una clase que se compone de varios métodos, y las acciones apuntan a uno de estos métodos. Si no se especifica una accione llamaremos a una acción llamada ‘index’.
Finalmente, obtenemos el path complete del archive controlador concatenando el path con el nombre del controlador y su extensión.
Ahora que la solicitud ha sido analizada se la envía al método delegate() para cargar el controlador y ejecutar la acción. El método delegate() complete sería algo así::
function delegate()
{
// Analiza la ruta
$this->getController($file, $controller, $action, $args);
// El archivo existe?
if (is_readable($file) == false) {
die ('404 Not Found');
}
// Incluye el archivo
include ($file);
// Inicializa la clase
$class = 'Controller_' . $controller;
$controller = new $class($this->registry);
// Existe la Accion?
if (is_callable(array($controller, $action)) == false) {
die ('404 Not Found');
}
// Ejecuta la acción
$controller->$action();
}
Luego de tener analizada la solicitud con el metodo getController(), primero debemos asegurarnos que el archivo existe y si no retornar un sencillo mensaje de error.
La siguiente cosa que debemos hacer es incluir el archivo controlador, e inicializar la clase, que siempre debe ser llamada Controller_[nombre]. Luego aprenderemos mas sobre el controlador.
Entonces verificamos si la acción existe y es ejecutable utilizando is_callable(). Finalmente, ejecutamos la acción, que completa el rol del router.
Ahora que tenemos funcionando completamente el método delegate(), agregamos las siguientes líneas al archivo index.php:
$router->delegate();
Si intentan ejecutar el archivo ahora, obtendremos el siguiente error por que no tenemos creado el directorio ‘controllers’:
Fatal error: Uncaught exception 'Exception' with message 'Invalid controller path: `g:\Projects\PHPit\content\simple mvc php5\demo\controllers\`' in g:\Projects\PHPit\content\simple mvc php5\demo\classes\router.php:18 Stack trace: #0 g:\Projects\PHPit\content\simple mvc php5\demo\index.php(13): Router->setPath('g:\Projects\PHP...') #1 {main} thrown in g:\Projects\PHPit\content\simple mvc php5\demo\classes\router.php on line 18
O obtendremos ‘404 Not Found’ porque no tenemos controladores creados aun. Pero ese es el tema de la siguiente parte de este tutorial.
Otros post
Este post ha sido visto 3802 veces

Octubre 6th, 2008 at 3:06 pm
Muy interesante el articulo, podrias poner un ejemplo por favor?
Marzo 17th, 2009 at 9:54 pm
Cuando podras subir o tener listas las partes que faltan???, ya que me ha servido mucho pero se aprecia que falta algo.
Espero tu respuesta
Junio 7th, 2009 at 4:50 pm
que lastima no ver la continuacion de este tutorial
Agosto 4th, 2009 at 7:34 pm
Pueden encontrar más info sobre controlador, modelo y vista en:
http://www.jourmoly.com.ar/introduccion-a-mvc-con-php-primera-parte/