Patrón MVC en PHP

Guía completa del Patrón MVC en PHP

El Patrón Modelo Vista Controlador (MVC) es uno de los patrones de diseño más utilizados y populares en el desarrollo de aplicaciones web. Su objetivo es separar la lógica de negocio, los datos y la interfaz de usuario en tres componentes distintos (Modelo, Vista y Controlador), haciendo que el código sea más flexible, escalable y fácil de mantener.

En este artículo profundizaremos en los conceptos clave del patrón MVC, sus ventajas, la forma de implementarlo en PHP y código de ejemplo para entender cómo funcionan sus componentes. Además, abordaremos aspectos importantes como el uso de POO con MVC y consejos prácticos para su aplicación en proyectos reales.

Si deseas aprender cómo crear aplicaciones PHP robustas y profesionales, utilizando uno de los patrones más efectivos, este artículo te guiará paso a paso por el mundo del MVC. ¡Comencemos!

¿Qué es el Patrón MVC?

El Patrón Modelo Vista Controlador o MVC es una forma de organizar el código de una aplicación en tres componentes principales, los cuales se encargan de tareas específicas:

  • - Modelo: encapsula la lógica de negocio y los datos. Se conecta a la base de datos y realiza operaciones sobre ella.

  • - Vista: presenta la interfaz de usuario. Muestra los datos solicitados por el usuario.

  • - Controlador: intercepta las peticiones del usuario y responde llamando al Modelo y a la Vista.

La idea principal del MVC es separar estos tres componentes, de forma que modificar o actualizar uno de ellos no afecte a los demás. Por ejemplo, se pueden crear nuevas Vistas sin tener que cambiar el Modelo o Controlador.

El flujo de trabajo típico en una aplicación MVC es el siguiente:

  • 1. El usuario realiza una petición a la aplicación, normalmente accediendo a una URL o submit de un formulario.

  • 2. El Controlador recibe la solicitud y decide qué Modelo y Vista utilizar.

  • 3. El Controlador interactúa con el Modelo para recuperar los datos necesarios de la base de datos u otras fuentes.

  • 4. El Modelo devuelve los resultados de la petición al Controlador.

  • 5. El Controlador pasa estos datos a la Vista correspondiente.

  • 6. La Vista genera el output final en HTML para ser enviado y renderizado en el navegador del usuario.

Así se completa el ciclo request-response de cada petición manteniendo separados en todo momento Modelo, Vista y Controlador. Esto brinda grandes beneficios.


Componentes del Patrón MVC

Veamos en más detalle qué función cumple cada componente en el patrón MVC:

Modelo

El Modelo representa los datos y lógica de negocio de la aplicación:

  • - Accede a la capa de almacenamiento de datos (base de datos, archivo, API externa, etc).

  • - Contiene funciones para consultar, insertar, actualizar y eliminar datos.

  • - Puede implementar la validación de datos y reglas de negocio.

  • - Se comunica con el Controlador para devolverle los resultados.

En PHP los Modelos suelen ser clases que contienen las consultas a la base de datos y los métodos para realizar operaciones CRUD sobre ella.

Vista

La Vista se encarga de la presentación visual de la información con la que interactúa el usuario:

  • - Muestra los datos recibidos del Controlador usualmente en formato HTML.

  • - No realiza ningún procesamiento sobre los datos.

  • - Puede contener HTML estático, CSS y código que indique cómo presentar los datos.

  • - Existen vistas diferentes para cada tipo de presentación deseada.

Las Vistas más comunes son archivos PHP que contienen HTML mezclado con código para mostrar los datos dinámicamente. También pueden utilizarse plantillas como Twig.

Controlador

El Controlador hace de intermediario entre el Modelo y la Vista:

  • - Recibe las solicitudes HTTP entrantes.

  • - Invoca los métodos del modelo para recuperar o actualizar datos.

  • - Selecciona la vista apropiada y le pasa los datos.

  • - Maneja la navegación y el flujo de la aplicación.

Los Controladores suelen ser clases PHP donde cada método representa una ruta o URI en particular. Contienen lógica para decidir qué hacer en cada petición.

Ventajas del Patrón MVC

El patrón MVC ofrece muchos beneficios, incluyendo:

  • - Separación de conceptos. Cada componente tiene una responsabilidad singular, haciendo que el código sea más legible y mantenible.

  • - Reutilización. Se pueden reutilizar las Vistas y Modelos en diferentes aplicaciones.

  • - Trabajo en equipo. Varios programadores pueden trabajar de forma paralela en los diferentes componentes.

  • - Interfaces flexibles. Se pueden cambiar fácilmente las Vistas sin afectar el resto de la aplicación.

  • - Mantenimiento simplificado. Al estar desacoplados, es más fácil realizar cambios y actualizaciones.

  • - Código limpio. La separación promueve un código bien organizado sin duplicidades.

  • - Bajo acoplamiento. Cada capa opera de forma independiente, reduciendo la dependencia entre ellas.

  • - Alta cohesión. Cada capa se encarga de una tarea específica en el sistema.

Claramente el patrón MVC fomenta muchas buenas prácticas de desarrollo de software, haciéndolo ideal para crear aplicaciones web robustas y escalables.


Implementación del Patrón MVC en PHP

Para implementar el patrón MVC en PHP debemos organizar nuestro código en las tres capas ya mencionadas. Veamos los aspectos clave a tener en cuenta.

Estructura de Directorios

Lo primero es establecer una estructura de directorios que represente los componentes MVC:

/app
  /Controllers
  /Models
  /Views
public
  /css
  /js
  index.php
Estructura de Directorios Patrón MVC en PHP
  • - /app: contendrá todo el código de nuestra aplicación MVC.

  • - /Controllers: clases controladores.

  • - /Models: clases modelo que acceden a la base de datos.

  • - /Views: plantillas de las vistas para presentar contenido.

  • - /public: directorio web público con CSS, JS y otros assets.

  • - index.php: punto de entrada que carga el núcleo del framework.

Esta es una estructura común, pero puede ser adaptada si se necesita. Lo importante es separar las capas MVC.

Controladores

Anteriormente vimos que los Controladores manejan las peticiones HTTP y la lógica de nuestra aplicación. Se suelen crear como clases PHP con métodos que representan acciones específicas.

Por ejemplo, un controlador Pages tendría métodos como home(), about(), etc. Y un controlador Users métodos como register(), login(), profile(), etc.

// Ejemplo de Controlador Pages

class Pages {

  public function home() {
// lógica para página home
  }

  public function about() {
// lógica para página about
  }

}
Controladores Patrón MVC en PHP

Modelos

Los Modelos representan los datos que maneja nuestra aplicación. Normalmente contienen funciones para consultar, insertar, actualizar y eliminar registros de una base de datos.

Se suelen crear como clases PHP simples, una por cada entidad o tabla de la base de datos:

// Ejemplo de Modelo User

class User {

  public function findAll() {
// consulta SQL para obtener todos los usuarios
    return $resultado;
  }

  public function register($data) {
// insertar nuevo usuario
  }

}
Modelos Patrón MVC en PHP

Vistas

Las Vistas generan la representación visual de la información que se envía al navegador. En PHP normalmente se crean archivos con extensión .php dentro de un directorio /Views.

Existe una vista por cada tipo de contenido que se desee mostrar. Por ejemplo home.php, about.php, contact.php, etc. Las vistas:

// Ejemplo de Vista home.php

<?php foreach($posts as $post): ?>

  <h2><?=$post['title']?></h2>

  <p><?=$post['body']?></p>

<?php endforeach; ?>
Vistas Patrón MVC en PHP

Ejemplo práctico de MVC en PHP

Para entender mejor cómo interactúan los componentes en un proyecto MVC, desarrollaremos una sencilla aplicación de gestión de posts o artículos.

La aplicación tendrá las siguientes funciones:

  • - Página de inicio (/) para ver todos los posts.

  • - Página de creación de posts (/posts/create) con formulario.

  • - Página de detalle (/posts/show/5) para ver un post individual.

Empezaremos creando la base de datos con una sola tabla posts que tenga los campos id, title y body para representar cada post. En mi caso utilizo MySQL Workbench

CREATE SCHEMA `ejemplo-mvc-php` ;
Creación Base de Datos

Con la base de datos implementada creamos la tabla Posts:

CREATE TABLE `ejemplo-mvc-php`.`posts` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(45) NULL,
  `body` VARCHAR(45) NULL,
  PRIMARY KEY (`id`));
Crear Tabla Post

Por último rellenamos la tabla con 5 registros:

INSERT INTO `ejemplo-mvc-php`.`posts` (`title`, `body`) VALUES ('Titulo 1', 'Cuerpo 1');
INSERT INTO `ejemplo-mvc-php`.`posts` (`title`, `body`) VALUES ('Titulo 2', 'Cuerpo 2');
INSERT INTO `ejemplo-mvc-php`.`posts` (`title`, `body`) VALUES ('Titulo 3', 'Cuerpo 5');
INSERT INTO `ejemplo-mvc-php`.`posts` (`title`, `body`) VALUES ('Titulo 4', 'Cuerpo 4');
INSERT INTO `ejemplo-mvc-php`.`posts` (`title`, `body`) VALUES ('Titulo 5', 'Cuerpo 5');
Insertar Registros

Luego creamos la estructura MVC básica:

/app
  /Controllers
    PostsController.php
  /Core
    DB.php
  /Models
    Post.php
  /Views
    home.php
    show.php
public
  /css
  index.php
Directorio Ejemplo Práctico

Conexión con la base de Datos

Comenzamos editando nuestro archivo app/Core/DB.php configurando nuestra conexión con nuestra base de datos, revisa las credenciales de tu base de datos

<?php
// app/Core/DB.php
class DB
{
    private static $instance = null;

    /**
     * Conexión con nuestra base de datos
     */
    public static function getInstance()
    {
        if (!self::$instance) {
            self::$instance = new PDO('mysql:host=localhost;dbname=ejemplo-mvc-php', 'root', '');
        }
        return self::$instance;
    }
}
Configuración Code DB

Rutas

En nuestro index.php vamos a configurar el sistema de rutas que llamará a los controladores

<?php
require 'app/Core/DB.php';
require 'app/Controllers/PostsController.php';

define('VIEWS_PATH', __DIR__ . '/app/Views');
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

switch ($uri) {
    case '/':
        $controller = new PostsController();
        $controller->index();
        break;
    case '/show':
        $id = isset($_GET['id']) ? $_GET['id'] : null;
        $controller = new PostsController();
        $controller->show($id);
        break;
    default:
        http_response_code(404);
        echo "Página no encontrada";
        break;
}
Configuración Index

Controlador Posts

Define los métodos index y show que cargan las vistas luego de obtener los posts desde el modelo.

<?php
require 'app/Models/Post.php';

class PostsController
{
  /**
   * Función que envía todos los Post a la vista Home
   */
  public function index()
  {
    $posts = Post::getAll();
    require VIEWS_PATH . '/home.php';
  }

  /**
   * Función que envía el post seleccionado a la vista Show
   */
  public function show($id)
  {
    $post = Post::getById($id);
    require VIEWS_PATH . '/show.php';
  }
}
Configuración Controlador

Modelo Post

Encapsula la lógica para consultar posts desde la base de datos. Otros métodos pueden ser creados para insertar, actualizar y eliminar registros.

<?php
class Post
{
    public static function getAll()
    {
        $db = DB::getInstance();
        // Sentencia preparada para prevenir inyección SQL
        $stmt = $db->prepare('SELECT * FROM posts');
        $stmt->execute();
        return $stmt->fetchAll();
    }

    public static function getById($id)
    {
        $db = DB::getInstance();

        // Sentencia preparada para prevenir inyección SQL
        $stmt = $db->prepare('SELECT * FROM posts WHERE id = :id');

        // Sanitizamos la entrada
        $id = filter_var($id, FILTER_VALIDATE_INT);

        // Vinculamos el parámetro :id 
        $stmt->bindParam(':id', $id);
        $stmt->execute();
        // Obtenemos el post
        $post = $stmt->fetch();

        // Retornamos instancia de Post o null si no existe
        if ($post) {
            return $post;
        } else {
            return null;
        }
    }
}
Configuración Modelo

Vistas del ejemplo

Este es el app/Views/home.php cuya función es la de iterar y mostrar los posts pasados por el controlador.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Home</title>
</head>

<body>
    <?php foreach ($posts as $post) : ?>

        <h1><?= $post['title'] ?></h1>

        <p><?= $post['body'] ?></p>

    <?php endforeach; ?>
</body>

</html>

Por último el app/Views/show.php

muestra los detalles de un post individual.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Show</title>
</head>

<body>
    <h1><?= $post['title'] ?></h1>

    <p><?= $post['body'] ?></p>
</body>

</html>

Con esto ya tendríamos una aplicación MVC simple en PHP. El Controlador maneja la navegación, el Modelo abstracta la base de datos y las Vistas presentan los datos.

El flujo para mostrar todos los posts sería:

  • 1. Se hace una petición GET a / que entra al método index()del controlador Posts.

  • 2. El controlador pide al modelo Post todos los registros con Post::all( .

  • 3. El modelo ejecuta la consulta SQL y devuelve los posts.

  • 4. El controlador carga la vista home.php y le pasa los posts.

  • 5. La vista genera el HTML de la lista de posts y lo envía al navegador.

Y el proceso sería similar para mostrar un post individual en la ruta /posts/show&id=5.

Modelo en MVC con PHP

El Modelo es un componente clave en la arquitectura MVC. Para construir modelos efectivos en PHP debemos tener en cuenta varios principios y buenas prácticas:

  • - Acceder a la base de datos a través de una capa de abstracción como PDO en lugar de la extensión mysql nativa. Esto permite cambiar fácilmente el sistema de base de datos subyacente.

  • - Crear una clase de modelo base con funciones genéricas para heredar, como métodos para hacer consultas preparadas a la base de datos.

  • - Definir un modelo como clase para cada entidad o recurso de negocio que se necesite manejar. Por ejemplo, los modelos User, Post, Comment, Product, etc.

  • - Implementar un repositorio o tabla de datos para abstraer la lógica de base de datos. Los modelos utilizan el repositorio para persistir información.

  • - Validar los datos entrantes antes de insertar o actualizar registros en la base de datos.

  • - Mapear los resultados de consultas a objetos del modelo para encapsular los datos y facilitar su uso en otras capas de la aplicación.

  • - Mantener los modelos delgados, con una responsabilidad clara. La lógica de negocio puede extraerse a una capa de servicios.

  • - Almacenar en caché resultados de consultas cuando sea posible para mejorar el rendimiento.

Seguir principios SOLID y patrones como Unit of Work y Repository contribuye a crear modelos mantenibles y escalables.

Vistas en MVC con PHP

A la hora de trabajar con vistas en el patrón MVC es útil tener en cuenta:

  • - Separar la presentación de la lógica mediante el uso de plantillas como Twig o PHP puro. Nunca poner consultas a bases de datos ni otra lógica en las vistas.

  • - Pasar los datos necesarios para la vista desde el controlador. Las vistas solo deben leer y mostrar estos datos, no acceder a otras fuentes de información.

  • - No repetir código HTML en las distintas vistas. Usar includes, herencia de plantillas y layouts para crear interfaces consistentes.

  • - Mantener las vistas simples, enfocadas en presentar los datos. La lógica condicional en las plantillas debe ser mínima.

  • - Evitar tener lógica de control de flujo compleja en las vistas. Si es necesario, extraerla a controladores o componentes reutilizables.

  • - Nombrar las vistas de forma explícita según la información que muestran, como users.php o posts.php.

  • - Usar un motor de plantillas que permita aplicar escape automático de output XSS para evitar problemas de seguridad.

  • - Implementar un sistema de caché de fragmentos de vistas o páginas finales para mejorar el performance cuando se muestran datos que no cambian frecuentemente.

  • - Considerar el uso de APIs asíncronas y Javascript en el front-end para recuperar datos JSON y renderizar el HTML de forma dinámica sin necesidad de recargar la página.

Al crear vistas desacopladas y reutilizables que solo se encarguen de la presentación, se facilita el desarrollo y testing de la aplicación.

Controladores en MVC con PHP

Los controladores son la capa encargada de manejar el flujo de la aplicación y la lógica que coordina el modelo y la vista. Algunas buenas prácticas para controladores MVC en PHP:

  • - Crear un controlador como clase para agrupar el código relacionado a una entidad o recurso en particular, como Users, Posts, Products, etc.

  • - Definir métodos públicos para las acciones comunes como show(), index(), delete(), etc. que se asocian a las rutas.

  • - Mantener los controladores delgados evitando poner demasiada lógica de negocio. Extraer lógica compleja a clases de servicios.

  • - Si los controladores crecen demasiado, reorganizar el código en controladores más pequeños y enfocados en tareas específicas.

  • - Los nombres de métodos deben indicar la acción que realizan. Por ejemplo, storePost() en vez de save().

  • - Validar y sanear cualquier dato proveniente de la request HTTP antes de usarlo. No confiar nunca en el input del usuario.

  • - Usar inyección de dependencias para pasar modelos u otros objetos a los métodos del controlador en lugar de crear dependencias directas.

  • - Retornar vistas o JSON la mayoría de veces en lugar de imprimir o enviar output directamente desde el controlador.

  • - Redirigir al usuario a otra página luego de acciones POST exitosas en lugar de refrescar la página actual.

  • - Manejar excepciones de forma adecuada en los controladores y mostrar mensajes de error amigables al usuario.

Al seguir estas prácticas los controladores se mantienen simples, testeables y fáciles de mantener.

POO en el Patrón MVC con PHP

Aunque se puede implementar el patrón MVC con PHP procedural, el enfoque orientado a objetos brinda muchos beneficios como:

  • - Permite modelar el dominio mediante clases y objetos que encapsulan datos y comportamiento.

  • - Favorece el bajo acoplamiento y alta cohesión mediante el ocultamiento de información y comunicación mediante interfaces.

  • - Promueve la reutilización de código al permitir herencia entre clases controladoras y modelos relacionados.

  • - Los objetos de modelo tienen un estado interno que puede persistir entre peticiones Web mediante la sesión.

  • - Se puede usar polimorfismo para intercambiar objetos relacionados como distintos modelos que heredan de una misma clase base.

  • - La inyección de dependencias es viable para crear objetos de forma flexible y desacoplada.

Algunas implementaciones comunes de POO para MVC:

  • - Una interfaz IModel para declarar firmas de métodos comunes que deben implementar los modelos.

  • - Una clase BaseModel con funciones reutilizables para extender modelos específicos.

  • - Una interfaz IController para forzar cierta estructura en los controladores.

  • - Un controlador base BaseController con código compartido por subclases.

  • - Una clase Request para encapsular los parámetros y datos de la petición HTTP entrante.

  • - Una clase App que instancie y ensamble los componentes mediante un contenedor.

Aplicar POO al patrón MVC permite construir aplicaciones mejor estructuradas y aprovechar las ventajas de la programación orientada a objetos.


Conclusión sobre el Patrón MVC en PHP

A lo largo de esta clase hemos visto qué es el patrón MVC, sus ventajas, forma de implementación en PHP y ejemplos prácticos de código para entender su funcionamiento.

Podemos concluir que MVC es una excelente opción para desarrollar aplicaciones web robustas, mantenibles y escalables utilizando PHP.

Al separar la lógica del negocio, los datos y la interfaz de usuario en componentes independientes, se consigue un código más organizado, flexible y de fácil testing.

MVC promueve buenas prácticas de programación como el bajo acoplamiento, alta cohesión y reutilización de código. Permite que múltiples programadores puedan trabajar en paralelo sobre la aplicación.

Si bien requiere una curva inicial de aprendizaje y puede agregar algo de complejidad, los beneficios superan ampliamente los costos en aplicaciones reales.

Te invitamos a aplicar los conceptos de MVC en tus próximos proyectos PHP para elevar la calidad de tu código y crear aplicaciones más profesionales.


Preguntas Frecuentes

MVVM (Modelo Vista - Vista Modelo) es un patrón derivado de MVC que funciona bien para interfaces ricas en JavaScript. En vez de Controladores tiene ViewModels que exponen datos a las Vistas. MVC es mejor para aplicaciones Web tradicionales renderizadas del lado del servidor.

Algunos populares son Laravel, Symfony, CakePHP, CodeIgniter y Zend Framework. Todos ellos proveen estructura y herramientas para construir aplicaciones MVC, aunque con enfoques diferentes.

Sí, es totalmente posible implementar MVC desde cero con PHP puro. Algunos desarrolladores prefieren este control total. Idealmente se requiere utilizar buenas prácticas y principios de diseño de software para obtener los beneficios completos.

Una forma es extraer parte de esa lógica a clases de servicios independientes que sean llamados desde el controlador. Otra opción es delegar cierta lógica a los modelos si está fuertemente relacionada a los datos.

Los repositorios ayudan a desacoplar la lógica de obtención de datos de los modelos. Pero no siempre son requeridos, en aplicaciones sencillas los modelos pueden consultar la base de datos directamente.

Deja un Comentario

¡Bienvenido a nuestro sitio web!

Este sitio utiliza cookies para mejorar tu experiencia de navegación y proporcionar funciones adicionales relacionadas con el análisis de tráfico y el rendimiento del sitio. Política de cookies.