Tutorial MVC con PHP

¿Qué es MVC?

Modelo Vista Controlador es un patrón de arquitectura de software que se utiliza mucho en aplicaciones web, separandola en tres capas (modelo, controlador y vista)

  • El Modelo se encarga de interactuar con la base de datos y también se ejecuta las reglas de negocio.
  • El Controlador procesa las peticiones de la pagina web (vista), y envía estos datos a la capa modelo, para que esta le devuelva la información adecuada para mostrarla en la capa vista.
  • La vista es el código HTML que se muestra al usuario, con la información proveniente del controlador.

¿Porqué útilizar MVC?

El fácil mantenimiento de código en un futuro, ya que al estar separadas los distintos procesos según su tipo.
Si quisieramos por ejemplo cambiar de tipo de base de datos, solo tendremos que cambiar la capa modelo.

Para una mejor percepción de esta arquitectura, muestro la transformación de una lista de artículos de un blog.

Este código es lo necesario para cumplir con el proposito de listar los artículos

<?php 
$cn = mysql_connect('local','usu','clave');
mysql_select_db('db', $cn);
 
$r=mysql_query('SELECT *FROM articulo', $cn);
?>

<h1>Listado de Artículos</h1>
<table>
  <tr>
    <td>Fecha</td>
    <td>Titulo</td>
  </tr>
</table>

<?php

while($fila= mysql_fetch_array($r, MYSQL_ASSOC))
{
    echo "<tr>";
    echo "<td> ".$fila['fecha']." </td>";
    echo "<td> ".$fila['titulo']." </td>";
    echo "</tr>";
}

?>

</table>

<?php

mysql_close($cn); 
?>

Observaciones

  • En la misma página nos conectamos al servidor ( solo funcionara si es MySQL ) y seleccionamos una base de datos.
  • Realizamos una consulta (no hay manejo de errores y/o excepciones).
  • Pintamos el código HTML (combinamos código HTML dentro del código PHP, dejando los tags (<tr>, <td>) ilegibles para la persona que implemente los estilos).

Utilizando el Controlador y la Vista

El ejemplo anterior los separaremos en dos archivos, uno se llamara controlador y el otro vista.

controlador.php

<?php
$cn = mysql_connect('local','usu','clave');
mysql_select_db('db', $cn);
 
$resultado = mysql_query('SELECT *FROM articulo', $cn);
$articulos = array();

while($articulo = mysql_fetch_assoc($resultado))
{
    $articulos[] = $articulo;
}

mysql_close();

require('vista.php');
?>

vista.php

<h1>Listado de Articulos</h1>
<table>
    <tr>
      <td>Fecha</td>
      <td>Titulo</td>
    </tr>

    <?php foreach($articulos as $articulo): ?>
    <tr>
        <td><?php echo $articulo['fecha']?></td>
        <td><?php echo $articulo['titulo']?></td>
    </tr>
<?php endforeach;?>
</table>

De esta manera tenemos separada en el controlador.php casi todo el código php con la lógica de negocios, mientras que en vista.php solo recorremos un array con datos.

Lo recomendable en la vista seria utilizar instrucciones PHP mas conocidad, como: if, endif, foreach, endforeach. Y no utilizarlas con llaves “{“, ya que dificulta reconocer donde empieza y termina.

Otro problema seria si queremos utilizar nuevamente el listar articulo en otra pagina, tendríamos que reescribir el controlador.php de nuevo.
Para esto separaremos el controlador(controlador.php) en modelo.php y controlador.php.

Utilizando el Modelo

modelo.php

<?php

function getArticulos()
{
    $cn = mysql_connect('localhost', 'usuario', 'clave');
    mysql_select_db('db', $cn);
     
    $resultado = mysql_query('SELECT fecha, titulo FROM articulo', $cn);
    $articulos = array();
    
    while($articulo = mysql_fetch_assoc($resultado))
    {
        $articulos[] = $articulo;
    }
    
    mysql_close();    

    return $articulos;
}
?>

controlador.php

require('modelo.php');

$articulos = getArticulos();

require('vista.php');

Despues de esta separación el controlador quedaría tan solo como un agente para pasar datos del modelo hacia la vista, pero en aplicaciones mas complejas el controlador es quien realiza las tareas de autenticación de usuarios, manejo de sesiones, filtrar y validar entradas de datos por GET o POST.

 

Cambiando el gestor de Base de Datos

La respuesta seria, cambiar todas las funciones del modelo (mysql_connect, mysql_query, …) por las correspondientes, y eso nos tomaría mucho tiempo.
Para hacer un mejor uso de MVC o mejor dicho cambiando el patrón un poco, se podría separar el modelo en dos capas:

  • La capa de Acceso a Datos
  • La capa de Abstracción de la Base de Datos

Si se diera el caso de cambiar de gestor de base de datos, solo tendríamos que actualizar la capa de abstracción de la base de datos

Ejemplo de las dos capas

Abstracción de datos

function crearConexion($servidor, $usuario, $clave)
{
  return mysql_connect($servidor, $usuario, $clave);
}
 
function cerrarConexion($cn)
{
  mysql_close($cn);
}
 
function consulta($consulta, $base_datos, $cn)
{
  mysql_select_db($base_datos, $cn);
 
  return mysql_query($consulta, $cn);
}
 
function getResultado($resultado, $tipo = MYSQL_ASSOC)
{
  return mysql_fetch_array($resultado, $tipo);
}

Acceso a Datos

function getTodosLosArticulos()
{
  $cn = crearConexion('localhost', 'usuario', 'clave');
 
  $resultado=consulta('SELECT fecha, titulo FROM articulo', 'db', $cn);
 
  $articulos = array();
  while ($articulo = getResultado($resultado))
  {
     $articulos[] = $articulo;
  }
 
  cerrarConexion($cn);
 
  return $articulos;
}

Ahora tenemos la capa de Acceso a Datos sin ninguna dependencia de funciones de alguna gestor de base de datos, y podremos reutilizar las funciones de la capa de abstracción de base de datos en otras funciones de acceso a datos de nuestro modelo.

También te puede interesar

14 Comments

  1. El mejor IDE para PHP - Craftyman Blog
    feb 19, 2009 @ 07:10:45

    [...] Sobre la generación de código, algunos IDE’s tienen la opción de crear getters y setters para las variables de una clase, y para que tipo de PHP es, por ejemplo: un metodo para PHP4 seria “function get_usuarios()” en cambio con el estandar para PHP5 seria de esta forma “public function getUsuarios()”. Otra opción serian la generación de código para la conexion a la base de datos, pero esta función para mi opinión, no debería recomendarse, ya que es mejor realizar una clase de abstracción a la base de datos como escribí en mi anterior POST (MVC en PHP). [...]

  2. Crysfel
    mar 09, 2009 @ 12:32:04

    Hace varios años yo lo hacía así y me resultaba, ahora lo hago implementando conceptos de POO y el código resulta mucho mas entendible, encapsulado y se facilita el mantenimiento.

    saludos

  3. traza
    abr 30, 2009 @ 20:22:23

    Lo mejor del articulo: el codigo que nos presentas. Muchas gracias me sera de mucha ayuda

  4. Yerson
    jul 08, 2009 @ 19:29:48

    Excelente aporte, busque mucho en la web una explicacion que me hiciera entender el concepto de framework y por fin encontre este sitio con esta explicacion tan clara como el agua. Muchas gracias!!! Ojala que publicara mas explicaciones relacionadas con el tema. — Desde Colombia —

  5. Michael
    ago 15, 2009 @ 22:17:57

    recomendacion: deberias poner la fuente de tus post este x ejemplo es un extracto de librosweb.es en el libro del framework symfony http://www.librosweb.es/symfony_1_0/capitulo2/el_patron_mvc.html igual vale el aporte.

    Salu2,
    k-suma

  6. Jorge Leguia
    abr 27, 2010 @ 09:11:08

    Buen articulo, pero ahora se utiliza clases para hacer todo eso y en la capa de abstraccion de Base de datos puedes utiliar PDO o adodb ..

    Saludos desde Lima- Peru

  7. berthely
    may 13, 2010 @ 22:33:12

    Información de mucha ayuda, suelo buscar en inglés, pero en esta ocación encontré la descripción mas rapidamente usable en este sitio.

  8. Jose
    ago 10, 2010 @ 10:24:29

    Un articulo muy interesante pero solo le veo utilidad para aquellos que quieran aprender y novatos, lo mejor para programar son los frameworks como symfony,codeigniter,cakephp.

    Un saludo,

  9. Eduardo
    sep 14, 2010 @ 17:53:57

    Estimado excelente post, hace tiempo deseaba entender esa parte del MVC, muy clara tu explicacion, gracias

  10. MTN
    nov 12, 2010 @ 06:15:35

    Excelente Post !!! también lo busqué durante mucho tiempo. Es super útil como introducción para los que deseamos empezar a usar frameworks.

    Muchas Gracias !!!

  11. Roberto Lezcano
    ene 19, 2011 @ 08:37:15

    Es un ejemplo que con su simplicidad logra (para los no tan expertos) mostrar los beneficios del modelo vista controlador.

  12. leonardo
    jul 19, 2011 @ 13:08:26

    este es el error:
    ( ! ) Warning: Invalid argument supplied for foreach() in C:wampwwwpruebavista.php on line 4
    Call Stack
    # Time Memory Function Location
    1 0.0003 363520 {main}( ) ..controlador.php:0
    2 0.0065 371952 require( ‘C:wampwwwpruebavista.php’ ) ..controlador.php:6

  13. menes
    sep 20, 2011 @ 17:00:31

    A la funcion getArticulos() le falta un return $articulos para devolver el array.

  14. carlos
    dic 05, 2011 @ 11:03:20

    Bien, como hago un INSERT INTO