Afinando el mini MVC

Para afinar un poquito nuestro sistema nos convendría hacer que nuestros controladores y modelos no sean clases base, sino que extiendan de otras clases que contengan las funcionalidades básicas. De este modo todas las funcionalidades que agreguemos a nuestro **ControladorBase** (Base_Controller) y **ModeloBase** (Base_Model) serán heredadas por los controladores y modelos que utilicemos.

core/Base_Controller

<?php
abstract class Base_Controller {
    protected $view;

    function __construct() {
        $this->view = new View();
    }
}

Incluimos en este controlador base la creación de la instancia de la vista en el constructor, es decir que ya no será necesario hacer esto en los demás controladores. Debemos recordar que si en los controladores reemplazamos el constructor, debemos llamar al constructor de la clase base para poder tener la instancia de la vista (parent::__construct()).

Con esta clase base, nuestro controlador **Libros_Controller** nos quedaría de la siguiente manera:

<?php
class Libros_Controller extends Base_Controller
{
   public function listar()
   {
      //Incluye el modelo que corresponde
      require 'models/Libros_Model.php';

      //Creamos una instancia de nuestro "modelo"
      $Libros_model = new Libros_Model();

      //Le pedimos al modelo todos los libros
      $libros = $Libros_model->getLibros();

      //Pasamos a la vista toda la información que se desea representar
      $variables = array();
      $variables['libros'] = $libros;

      //Finalmente presentamos nuestra plantilla
      $this->view->show("listar.php", $variables);
   }
   public function ver ()
   {
      if ( !isset ( $_GET [ 'id' ] ) )
         die("No has especificado un identificador de libro.");

      $id = $_GET [ 'id' ];

      //Incluimos el modelo correspondiente
      require 'models/Libros_Model.php';

      //Le pide al modelo el libro con id = $id
      $libro = $libros = $Libros_model->getLibro($id);

      if ($libro === null)
         die("Identificador de libro incorrecto");

      //Pasamos a la vista toda la información que se desea representar
      $variables = array();
      $variables['libro'] = $libro;

      //Pasamos a la vista toda la información que se desea representar
      $this->view->show('libros_ver.php', $variables);
   }
}
?>

core/Base_Model

Similar a Base_Controller, nos permitirá ahorrarnos el paso de iniciar PDO en cada modelo. Esta clase podría tener muchísimas funcionalidades más y podría ahorrarnos escribir mucho código SQL si implementáramos en ella el patron ActiveRecord, por ejemplo, pero eso lo veremos con un framework real como CodeIgniter.

<?php
abstract class Base_Model
{
   protected $db;

   public function __construct()
   {
      $this->db = DBManager::getInstance()->getConnection();
   }
}

Ahora la clase Libros_Model extiende de Base_Model reutilizando el código de creación de la conexión desde clase base.

<?php
class Libros_Model extends Base_Model
{
   function getLibros()  {
      $result = $this->db->query('SELECT titulo, precio FROM libros');
      $libros = array();
      while ( $libro = $result->fetch() )
      $libros[] = $libro;
      return $libros;
   }

   function getLibro($id) {
      $query = 'SELECT * FROM libros WHERE id = ?';
      $stmt = $this->db->prepare($query);
      $stmt->execute(array($id));
      $libro = $stmt->fetch();
      return $libro;
   }
}

FrontController

El último cambio está en el FrontController pero es mínimo, solo es la inclusión de los archivos que contienen las clases Base para que puedan ser heredadas.

<?php
function __autoload($nombre) {
   require 'core/' . $nombre . '.php';
}
class FrontController
{
  static function main()
  {
    require 'config.php'; //Archivo con configuraciones.

    //Con el objetivo de no repetir nombre de clases
    //  nuestros controladores terminaran todos en _Controller.
    //Por ej, la clase controladora Libros, será Libros_Controller

    //Formamos el nombre del Controlador o en su defecto
    // tomamos que es el de Libros_Controller
    $controller = $config->get('DEFAULT_CONTROLLER');
    if(! empty($_GET['controller']))
      $controller = $_GET['controller'];

    //Lo mismo sucede con las acciones, si no hay accion
    //  tomamos index como accion
    $action = $config->get('DEFAULT_ACTION');
    if(! empty($_GET['action']))
      $action = $_GET['action'];

    $controller .= "_Controller";

    $controller_path = $config->get('CONTROLLERS_FOLDER') .
                       $controller . '.php';

    //Incluimos el fichero que contiene nuestra clase controladora solicitada
    if (!is_file($controller_path))
      throw new Exception('El controlador no existe ' .
                          $controller_path . ' - 404 not found');

    require $controller_path;

    //Si no existe la clase que buscamos y su método
    // mostramos un error
    if (!is_callable(array($controller, $action)))
      throw new Exception($controller . '->' . $action . ' no existe');

    //Si todo esta bien, creamos una instancia del controlador
    //  y llamamos a la accion
    $controller = new $controller();
    $controller->$action();
  }
}

Aclaraciones finales:

  1. Esta es una solución sencilla de cómo implementar el patrón Modeo-Vista-Controlador con programación orientada a objetos y patrones de diseño.
  2. Aunque hemos hablado de motor de plantillas, realmente son simples ficheros .php donde igual se puede incluir codigo php de cualquier tipo. Solo es una manera sencilla y liviana, sin tener que usar Smarty u otro motor de plantillas más avanzado.

No vamos a crear un framework desde cero porque desde la aparición de los frameworks PHP como **Symfony**, **Zend Framework**, **CakePHP** o **CodeIgniter** que integran todos los patrones vistos hasta ahora y algunos más, es una perdida de tiempo y de dinero. Los tres primeros frameworks PHP son las más utilizados en las empresas debido a su madurez, documentación y mejora continua. Hay empresas que han estado usando su propio framework sin saberlo durante años (hemo visto en pocos pasos como crear uno con funciones, requerir e incluir ficheros, etcétera) y han decidido migrar sus aplicaciones o crear nuevas aplicaciones desde 0 con algunos de estos frameworks.

Vamos a ver un ejemplo cómo crear un "Hola Mundo" en CodeIgniter:

<?php
   class Blog extends CI_Controller {
      function index()
      {
         echo 'Hola Mundo!';
      }
   }
?>

El fichero se llamará blog.php (igual que la clase) y se almacenará en el directorio **application/controller**. Para acceder a esa acción del controlador lo haríamos así: **/index.php/blog/** CodeIgniter se caracteriza por la convención en vez de la configuración, es decir, para no tener complicados ficheros de configuración (tipo Struts con ficheros XML infinitos y díficiles de mantener y entender) tenemos que seguir una serie de convenciones que facilitan el desarrollo y hacen mucho más rápida la ejecución de la aplicación.

results matching ""

    No results matching ""