Patron MVC con PHP

PATRÓN MVC CON PHP
Fundamento

El patrón MVC divide una aplicación Web en tres capas:

Vista: Se encarga de generar el HTML que se envía al browser.

Controlador: Recibe y procesa los requerimiento del usuario y comunica los resultados a la vista para que los envíe al browser.

Modelo: Implementa la lógica del negocio.

La siguiente figura muestra un diagrama de bloques del funcionamiento de este patrón.

Ejemplo Ilustrativo

Para este ejemplo estoy utilizando NetBeans 6.8.

El objetivo de este ejemplo es implementar una aplicación que permita realizar una suma o una multiplicación.

La estructura de la solución es la siguiente:

La clase Session se utiliza para manejar datos de sesión:

class Session {

   public static function existsAttribute($name){

      $rpta = FALSE;

      if( isset( $_SESSION[$name] ) ){

         $rpta = TRUE;

      }

      return $rpta;

    }

   public static function getAttribute($name) {

      $rpta = null;

      if( self::existsAttribute($name) ){

         $rpta = $_SESSION[$name];

      }

      return $rpta;

   }


   public static function getAttribute2($name) {

      $rpta = null;

      if( self::existsAttribute($name) ){

         $rpta = $_SESSION[$name];

         unset( $_SESSION[$name] );

      }

      return $rpta;

   }


   public static function setAttribute($name, $value) {

      $_SESSION[$name] = $value;

   }

}

La clase Matematica implementa la lógica, en este caso las dos operaciones: sumar y multiplicar.

class Matematica {

   public function suma($n1, $n2){

      $su = $n1 + $n2;

      return $su;

   }

   public function producto($n1, $n2) {

      $pr = $n1 * $n2;

      return $pr;

   }

}

El programa main.php implementa el formulario:

<?php

   session_start();

   require_once '../util/Session.php';


   $n1 = Session::getAttribute2("num1");

   $n2 = Session::getAttribute2("num2");

   $rpta = Session::getAttribute2("rpta");

   $action = Session::getAttribute2("action");

?>

<html>

   <head>

      <title>Operaciones Simples</title>

   </head>

   <body>

      <h1>Operaciones Simples</h1>

      <form method="post" action="../controller/Controller.php">

         <div>

            <label>Operacion</label>

            <select name="action">

               <option value="sumar">Suma</option>

               <option value="multiplicar">Producto</option>

            </select>

         </div>

         <div>

            <label>Número 1</label>

            <input type="text" name="num1">

         </div>

         <div>

            <label>Número 2</label>

            <input type="text" name="num2">

         </div>

         <div>

            <input type="submit" value="Procesar">

         </div>

      </form>

      <div>

         <table>

            <tr>

               <td>Action :</td>

               <td><?php echo($action); ?></td>

            </tr>

            <tr>

               <td>Num 1 :</td>

               <td><?php echo($n1); ?></td>

            </tr>

            <tr>

               <td>Num 2 :</td>

               <td><?php echo($n2); ?></td>

            </tr>

            <tr>

               <td>Rpta :</td>

               <td><?php echo($rpta); ?></td>

            </tr>

         </table>

      </div>

   </body>

</html>

En el programa tenemos un control de tipo SELECT, al que se le ha dado el nombre ACTION, este este control que comunica al controlador el método a ejecutar.

La clase Controller recibe los datos del formulario, entre ellos el método a ejecutar, hace uso del Model para resolver el problema y se comunica con el View para que genere el HTML que irá al browser.

El script de la clase controller es el siguiente:

<?php

session_start();
require_once '../model/Matematica.php';

require_once '../util/Session.php';
$action = $_REQUEST["action"];

$obj = new Controller();

$target = call_user_func(array($obj,$action));

header("location: $target");

return;

class Controller {

   public function sumar() {

      $n1 = $_REQUEST["num1"];

      $n2 = $_REQUEST["num2"];

      $mate = new Matematica();

      $rpta = $mate->suma($n1, $n2);

      Session::setAttribute("num1", $n1);

      Session::setAttribute("num2", $n2);

      Session::setAttribute("rpta", $rpta);

      Session::setAttribute("action", "Sumar");

      return "../view/main.php";

   }

   public function multiplicar() {

      $n1 = $_REQUEST["num1"];

      $n2 = $_REQUEST["num2"];

      $mate = new Matematica();

      $rpta = $mate->producto($n1, $n2);

      Session::setAttribute("num1", $n1);

      Session::setAttribute("num2", $n2);

      Session::setAttribute("rpta", $rpta);

      Session::setAttribute("action", "Multiplicar");

      return "../view/main.php";

   }

}

?>

Como podemos apreciar, la programación del controlador es bastante sencillo, el campo action podría ser un campo oculto en un formulario, incluso su valor puede ser manipulado con JavaScript y también se puede manejar con AJAX.

CODIGO FUENTE
En esta sección te presento un video de una aplicación web desarrollada SPRING FRAMEWORK y MYSQL.
Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.



Patron de Diseño Singleton

PATRÓN DE DISEÑO SINGLETON Contexto

Existen escenarios donde la aplicación solo necesita emplear una única instancia (objeto) de una clase, y esta instancia debe ser accesible desde diferentes partes del sistema.
Las clases que cumplen estas características suelen tener alguna de estas funciones:
  • Controlar el acceso a un recurso que por su naturaleza no admite el acceso concurrente (impresora, socket, fichero).
  • Obtener referencias de clases que actúan como servidoras de recursos (pool de conexiones).
  • Ejecutar código carente de estado (si el estado no cambia solo necesitamos una instancia).
  • Mantener un estado que debe ser globalmente único.
Por ejemplo, un sistema de log se ajusta a estas car
acterísticas porque:
  • Controla el acceso al recipiente de la información de log.
  • Toda la información del log se envía a través de un punto único.
  • Su único estado es la configuración, que es global y no suele variar.
Problema
Necesitamos crear una instancia de un clase que sea accesible globalmente, y que sea única.
Solución
El patrón Singleton proporciona la siguiente solución:
  • Hacer que la clase provea una instancia de sí misma.
  • Permitir que otros objetos obtengan esa instancia, mediante la llamada a un método de la clase.
  • Declarar el constructor como privado, para evitar la creación de otros objetos.
El diagrama UML correspondiente es muy simple y se muestra en la siguiente figura.

Este diagrama UML muestra como se implementa el patrón Singleton en una clase. Contiene una propiedad estática (el subrayado indica que es un método de clase) de nombre instancia, y que el método getInstancia() retorna un objeto de la misma clase.
Según la notación UML el número 1 en la esquina superior derecha, indica que solamente habrá una instancia de esta clase. El signo "-" en el constructor, lo señala como privado. Esto consigue que nadie aparte de la propia clase, pueda crear una instancia.
Implementación en PHP
Una primera implementación (GoF) de este patrón considera la instanciación de la clase en el método getInstancia(), tal como se ilustra a continuación:
class Demo{ 

    private static $instancia = null;  

    public static function getInstancia(){  

        if( self::$instancia == null ){  
            self::$instancia = new Demo();  
        }  
        return self::$instancia;  

    }  

    private function __construct() {  
    } 

    . . .   . . .  

}
Una segunda implementación considera la instanciación de la clase en la misma instrucción donde se declara la variable $instancia, tal como ilustra a continuación:

class Demo{ 

    private static $instancia = new Demo();  

    public static function getInstancia(){  
        return self::$instancia;  
    }  

    private function __construct() {  
    } 

    . . .   . . .  

}
El acceso a la instancia se realiza de la siguiente manera:
$demo = Demo::getInstancia();
Implementación en Java
Una primera implementación (Gof) de este patrón considera la instanciación de la clase en el método getInstancia(), tal como se ilustra a continuación:
public class Demo{ 

    private static Demo instancia = null;  

    public static Demo getInstancia(){  

        if( instancia == null ){  
            instancia = new Demo();  
        }  
        return instancia;  

    }  

    private Demo() {  
    } 

    . . .   . . .  

}
Una segunda implementación considera la instanciación de la clase en la misma instrucción donde se declara la variable instancia, tal como ilustra a continuación:
public class Demo{

private static Demo instancia = new Demo(); 

public static Demo getInstancia(){ 
return instancia; 
} 

private Demo() { 
}

. . .   . . . 

}
El acceso a la instancia se realiza de la siguiente manera:

    Demo demo = Demo.getInstancia();
Comentarios

Si estamos en un ambiente de un solo hilo (single-thread) la primera implementación es suficiente. En contrapartida, tiene serios problemas en entornos multihilo (multi-thread) dado que, debido a cuestiones de sincronización y concurrencia, puede crearse más de una instancia. ¿Cómo puede ser esto posible? Imaginemos que dos hilos evalúan la condición $instancia == null ( en Java: instacia == null ) y en ambos casos es verdadera. En este caso, ambos hilos crearán la instancia, violando el propósito del patrón Singleton.
Para solucionar el problema de que existe la posibilidad de crear mas de una instancia en entornos multihilo puede utilizar la segunda implementación.

CÓDIGO FUENTE

En esta sección te presento un video de una aplicación web desarrollada SPRING FRAMEWORK y MYSQL.

Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.