Como trabajar con el patron MVC del lado del cliente y del lado del servidor
MVC
es un patrón o
modelo de abstracción de desarrollo de software que separa los datos de una
aplicación, la interfaz de usuario, y la lógica de negocio en tres componentes
distintos. donde la vista es la página HTML y el código que provee de datos
dinámicos a la página. El modelo es el Sistema de Gestión de Base de Datos y la
Lógica de negocio, y el controlador es el responsable de recibir los eventos de
entrada desde la vista.
Modelo: Esta es la representación específica de la
información con la cual el sistema opera. En resumen, el modelo se limita a lo
relativo de la vista y su controlador facilitando las presentaciones visuales
complejas. El sistema también puede operar con más datos no relativos a la
presentación, haciendo uso integrado de otras lógicas de negocio y de datos
afines con el sistema modelado.
Vista: Este presenta el modelo en un formato adecuado
para interactuar, usualmente la interfaz de usuario.
Controlador: Este responde a eventos, usualmente acciones
del usuario, e invoca peticiones al modelo y, probablemente, a la vista.
Por consiguiente preparamos dos secciones más populares en la actualidad:
la una es el MVC con PHP y la otra es con javascript con un marco nuevo conocido como Backbone.js
MVC con javascript.
Cabe destacar que lo que más se utiliza son frameworks y en este caso no
deja de serlo así vamos a desarrollar una introducción con Backbone.js un framework que implementa el patrón MVC y nos ahorrará tiempo en desarrollar ciertas
cosas, “recuerden que un framework es una herramienta que nos ahorra tiempo en
desarrollo, pero que también nos sirve para conocer de su estructura.
Implementación del paradigma MVC
en Backbone.js
Backbone.js implementa cuatro clases:
Model
View
Controller o Router en versiones superiores a la 0.5.0
Collection
El objetivo de Backbone.js es
conseguir que las vistas escuchen cambios en el modelo y reaccionen
consecuentemente a esos cambios por si mismas. Si comparamos la estructura de
Backbone con un framework de la parte servidora como Rails las cosas cuadrarían
más o menos así:
Backbone.Model: Como los modelos en Rails sin métodos de clase.
Envuelve un resgistro de datos en la lógica de negocio
Backbone.Collection: Un grupo o colección de modelos en la parte
cliente que implementa lógica para ordenación filtrado y adición
Backbone.Router/Backbone.Controller: Como routes.rb en Rails y acciones
de controlador. Mapea URLs con funciones
Backbone.View: Una pieza de interfaz de usuario (UI) lógica y
reutilizable. Suele estar asociada a un modelo pero no tiene por que hacerlo
forzosamente
un link donde puedes entender mejor sobre este marco de trabajo y para que usarlo
aprendizaje a fondo
MVC en PHP
Es un patrón de arquitectura de software encargado de separar la lógica
de negocio de la interfaz de usuario y es el
más utilizado en aplicaciones web, ya que facilita la funcionalidad,
mantenibilidad, escalabilidad del sistema, de forma simple y sencilla
un nuevo concepto para crear
modelos
En esta etapa, podemos ampliar las referencias de PHP, incorporando un
nuevo
concepto: las interfaces.
“Las interfaces de objetos
permiten crear código con el cual especificar qué métodos deben
ser implementados por una clase,
sin tener que definir cómo estos métodos son manipulados.
Las interfaces son definidas
utilizando la palabra clave interface, de la misma forma que con
clases estándar, pero sin métodos
que tengan su contenido definido. Todos los métodos
declarados en una interfaz deben
ser public, ya que ésta es la naturaleza de una interfaz.
Una interface se define utilizando la palabra clave interface y se la
implementa utilizando
la palabra clave implements.
En varias ocasiones, las interfaces nos servirán para ampliar los
modelos.
Generamos la interface:
interface Postre {
public function set_ingredientes();
}
Implementamos
la interface:
class
Bizcochuelo implements Postre {
var
$ingredientes = array();
public function set_ingredientes() {
$this->ingredientes = array('harina'=>'2 tazas', 'leche'=>'1
taza',
'azucar'=>'1 taza', 'huevo'=>1
);
}
}
Extendemos una clase (que por
defecto, implementará la interface):
class
BizcochueloVainilla extends Bizcochuelo {
public
function set_ingredientes() {
$this->ingredientes['escencia
de vainilla'] = 'a gusto';
}
function __construct() {
parent::set_ingredientes();
$this->set_ingredientes();
}
}
Diferencia
entre Interfaces y Clases abstractas
Probablemente te preguntes ¿cuál es la diferencia entre una interface
y una clase
abstracta?
Créeme: todos nos lo hemos preguntado alguna vez :)
En principio, existe una
diferencia conceptual que a niveles “prácticos” tal vez no es del todo
clarificadora. Esta diferencia, radica en que las clases abstractas, no dejan
de ser “clases”, las cuales representan la “abstracción de un objeto” siguiendo
un orden de “relación jerarquíca” entre ellas: Clase B hereda de Clase A y
Clase C hereda de Clase B, pero no puede tener herencias múltiples, es decir no
puede heredar de más de una clase, ya que ellas, guardan una relación de orden
jerárquico entre sí.
class A { }
class B extends class A { } #correcto
class C extends class B { } #correcto
class D { } #correcto
class E extends class A, class D { } # incorrecto!!! no se puede hacer!!!
#
lo correcto sería:
class D extends class A { }
class E extends class D { }
A diferencia de las clases
abstractas, conceptualmente, las interfaces son solo un
conjunto de métodos
característicos de diversas clases, independientemente de la
relación que dichas clases
mantengan entre sí. De hecho, una misma clase, puede
implementar
múltiples interfaces:
interface A { }
interface B { }
interface C { }
class MiClase implements A, B, C { }
No obstante la diferencia
conceptual, podemos establecer claras diferencias prácticas,
que nos ayudarán a asimilar mejor
estos conceptos:
•
Las interfaces no pueden definir propiedades (de hecho, no poseen
propiedades
porque a diferencia de las clases
abstractas no tienen relación con un objeto, y
solo los objetos tienen
propiedades)
•
Las interfaces no pueden tener métodos definidos con su algoritmo
correspondiente (solo pueden
declarar los métodos pero no pueden indicar el
“qué” ni el “cómo” hacerlo,
mientras que las clases abstractas, sí pueden)
•
Las interfaces no pueden instanciarse porque no tienen referencias
asociadas a
objetos, mientras que las clases
abstractas no pueden instanciarse, porque sus
objetos son “entes abstractos”
que necesitan de una clase no abstracta para
definirse con exactitud y poder
ser instanciados.
•
Todos los métodos declarados en una interface deben ser públicos,
puesto que
la finalidad de una interface, es
brindar un “ámbito público de un modelo”. Las
clases abstractas, pueden tener
métodos abstractos tanto públicos como
protegidos (aquellos que deberán
ser obligatoriamente redefenidos por las clases
que la hereden) y métodos
privados que solo ella utilice.
Las
interfaces no pueden:
• Tener el mismo nombre que una
clase (PHP las interpreta como una clase más.
Crear una interface con el mismo
nombre que una clase, sería interpretado por
PHP como una “re-declaración de
clase”)
• Diferentes interfaces no pueden
tener nombres de métodos idénticos si serán
implementadas por la misma clase
Como hemos visto anteriormente,
la vista representa la interfaz gráfica del usuario (GUI),
es decir, es la encargada de
mostrar la información al usuario de manera “humanamente
legible”.
Vista:
la interfaz gráfica
Generalmente, en la práctica, no
somos los programadores quienes nos hemos de
encargar de la GUI. Es tarea que
corresponde a diseñadores Web o gráficos, según
aplique.
Como “arquitectos”, debemos tener
preparada la estructura de nuestra aplicación, para
que diseñadores puedan trabajar
libremente en la GUI, sin tener que acceder al código
PHP. En este libro, veremos
además, como evitar por completo que los diseñadores
tengan que implementar código PHP
en sus GUI y que programadores, tengamos que
implementar código HTML en
nuestras lógicas.
En principio, la parte gráfica de
las vistas (archivos HTML, imágenes, CSS, etc.), deberá
tener un directorio reservado
solo para ella. De esta forma, obtenemos varias ventajas
de trabajar con el patrón MVC:
•
Los archivos estáticos (HTML, CSS, imágenes e incluso JavaScript) pueden
almacenarse en un servidor
independiente con todos los beneficios que esto conlleva (al igual que sucede
con las bases de datos, los archivos estáticos también pueden independizarse)
•
Nos aseguramos de que el código estático (aquel desarrollado por
diseñadores),
no “rompa” el núcleo de la
aplicación
•
Permitimos a los diseñadores trabajar cómodamente en la libertad de
aplicar
todos los conocimientos y
herramientas inherentes a su área de conocimiento, sin
la presión de tener que
implementar un lenguaje de programación que desconocen,
les es poco familiar o
simplemente, la herramienta que utilizan para diseñar, suele dañarles el código
no-estático.
En
segundo lugar, cada plantilla – template - o archivo HTML, deberá
hacer referencia
“estática” a los datos que se
quieran reemplazar dinámicamente. Para esto, no será necesario implementar
código que no sea HTML. Veremos aquí como hacer referencia a estos datos, y más
adelante, veremos como la lógica de la vista se encargará de renderizarlos.
Supongamos que tenemos una
plantilla HTML, donde lo que necesitamos reemplazar de
manera dinámica, es: título de la
página, keywords y descripción. La mejor manera de
referenciar a estos datos,
facilitando la tarea a un diseñador, es haciendo una referencia
textual a éstos. Para que a la
vez, los programadores logremos diferenciar que allí se
incluyen datos dinámicos, una
buena práctica, es encerrar esa referencia textual entre
llaves.
Veamos
un ejemplo:
<!DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html
lang="es">
<head>
<meta
http-equiv="Content-Type" content="text/html;
charset=utf-8">
<title>{Título de la Página}</title>
43
POO y MVC en PHP – Eugenia Bahit
<meta name="title"
content="{Título de la
Página}">
<meta
name="keywords" content="{keywords}">
<meta
name="description" content="{descripción}">
<link
type="text/css" rel="stylesheet"
href="css/template.css">
</head>
<body>
<div
id="page">
<div
id="cab">
<img
alt="home page" src="img/logo.gif"></a>
</div>
<div
id="contenido">
<h1>{Título de la Página}</h1>
</div>
</div>
</body>
</html>
Veremos en el siguiente paso,
como la lógica de la vista, se encargará de reemplazar
estos datos.
Tenemos la plantilla que creó
nuestro diseñador. Es hora de reemplazar dinámicamente
los datos referenciados. Haremos
esto, paso a paso, como si de una receta de cocina se
tratara.
Primer
paso: crear un diccionario de datos
El diccionario de datos es el que
contendrá, literalmente hablando, un diccionario,
indicando cuales referencias
deben ser reemplazadas por cuáles datos, en forma
dinámica.
$diccionario
= array(
'Título
de la Página'=>'POO y MVC en PHP',
'keywords'=>'poo, mvc, php, arquitectura de software',
'description'=>'El
paradigma de la programación orientada a objetos con el
patrón
arquitectónico MVC en PHP'
);
Segundo
paso: obtener la plantilla HTML
Para traer la plantilla HTML,
vamos a utilizar la función file_get_contents()
de PHP,
y almacenar el contenido de ella,
en una variable.
$template = file_get_contents('/carpeta/template.html');
Tercer
paso: reemplazar el contenido en el anteúltimo paso, reemplazaremos los
datos, utilizando el bucle foreach de PHP para recorrer el diccionario, y la
función str_replace() de PHP, para reemplazar los mismos.
foreach
($diccionario as $clave=>$valor) {
$template
= str_replace('{'.$clave.'}', $valor, $template);
}
Cuarto
paso: mostrar el contenido final al usuario Por último, imprimiremos el
resultado obtenido en pantalla.
print
$template;
Y con esto, habremos concluido la
lógica de la vista, obteniendo en el navegador del
usuario, la siguiente salida
(vista de código fuente):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="es">
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=utf-8">
<title>POO y MVC en PHP</title>
<meta name="title" content="POO y MVC en PHP">
<meta name="keywords" content="poo, mvc, php,
arquitectura de software">
<meta
name="description" content="El paradigma de la programación
orientada a
objetos
con el
patrón
arquitectónico MVC en PHP">
<link type="text/css" rel="stylesheet"
href="css/template.css">
</head>
<body>
<div id="page">
<div id="cab">
<img alt="home page"
src="img/logo.gif"></a>
</div>
<div
id="contenido">
<h1>POO
y MVC en PHP</h1>
</div>
</div>
</body>
</html>
El
controlador
El controlador, aunque muchos de
ustedes no lo crean, es quien tal vez, lleva “la peor
parte”. En muchas ocasiones, es
complicado programar el controlador de manera previsible para que pueda
evolucionar, y generalmente, es sometido a refactorizaciones constantes,
incluso mayores que las que puede sufrir el modelo.
Recordemos que el controlador, es
quien debe interactuar con el modelo y con la vista.
Para hacerlo, deberá previamente
reconocer y manejar los distintos eventos del usuario,
para saber:
1. A qué modelo / modelos invocar
2. Qué y cuáles propiedades o
atributos del modelo/modelos modificar o parámetros
deberá entregar a sus métodos
3. A qué vista entregar la
información ¡Pobre hombre! Le toca una tarea extenuante. Veamos paso a paso,
como ayudar a este pobre “controller-man” en su tarea. Supongamos entonces, que
tenemos dos modelos:
Archivo
models.php
class ModeloUno {
var
$propiedad;
function
a($parametro) {
$this->propiedad
= $parametro;
}
}
class
ModeloDos {
var
$propiedad_1;
var
$propiedad_2;
function
b($param1, $param2) {
$this->propiedad_1
= $param1;
$this->propiedad_2
= $param2;
}
}
Y a la vez, tenemos dos vistas:
Template
vista_1.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html
lang="es">
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=utf-8">
<title>Vista Modelo 1</title>
</head>
<body>
<div
id="page">
<p>El
valor de la <b>propiedad</b> es
<b>{propiedad}</b></p>
</div>
</body>
</html>
Template vista_2.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="es">
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=utf-8">
<title>Vista Modelo 2</title>
</head>
<body>
<div
id="page">
<p>El
valor de <b>propiedad_1</b> es <b>{propiedad_1}</b>
mientras que el
de
<b>propiedad_2</b> es <b>{propiedad_2}</b></p>
</div>
</body>
</html>
Y la lógica de éstas, es la siguiente:
Archivo view.php
function
set_identificadores($vista) {
$identificadores
= array();
if($vista)
{
switch
($vista) {
case
'vista_1':
$identificadores
= array('propiedad');
break;
case
'vista_2':
$identificadores
= array('propiedad_1', 'propiedad_2');
break;
}
return
$identificadores;
}
}
function
armar_diccionario($vista, $data) {
$diccionario
= array();
$identificadores
= set_identificadores($vista);
if($identificadores) {
foreach ($identificadores as $identificador) {
if(array_key_exists($identificador, $data)) {
$diccionario[$identificador]
= $data[$identificador];
}
}
}
return
$diccionario;
}
function render_data($vista, $data) {
$html = '';
if(($vista)&&($data))
{
$diccionario
= armar_diccionario($vista, $data);
if($diccionario) {
$html = file_get_contents('html/'.$vista.'.html');
foreach
($diccionario as $clave=>$valor) {
$html = str_replace('{'.$clave.'}', $valor, $html);
}
}
}
print $html;
}
Entonces, nuestro controlador
procederá de la siguiente forma:
Primer paso: identificar el
modelo
Para esto, el controlador
previamente, tendrá que reconocer el evento que ejecuta el
usuario y saber como manejarlo.
Para ello, la forma de pensarlo “informáticamente”
sería:
si
usuario [evento] entonces [realizar acción]
En nuestro caso, los eventos
admitidos, serán llamdas por URL mediante el método
$_GET.
Primero, identificará el evento
respondiendo a las siguientes preguntas:
• ¿existe el evento de llamada
mediante “$_GET”?
• Si existe ¿a qué evento, el
usuario, quiere que responda?
Para esto, utilizará la siguiente
función:
function
capturar_evento() {
$vista
= '';
if($_GET) {
if(array_key_exists('vista', $_GET)) {
$vista
= $_GET['vista'];
}
}
return
$vista;
}
Devolviendo así, el evento
capturado a través de la variable “$vista”.
Con el evento “en la mano”, se
ocupará ahora de identificar el modelo:
function
identificar_modelo($vista) {
if($vista)
{
switch ($vista) {
case 'vista_1':
$modelo
= 'ModeloUno';
break;
case
'vista_2':
$modelo
= 'ModeloDos';
break;
default:
exit();
}
}
return $modelo;
}
Segundo paso: invocar al modelo efectuando los cambios
adecuados
Nuestro controlador, ya sabe a que modelo recurrir. Ahora, solo resta
invocarlo y
modificarlo si es necesario:
function
invocar_modelo($modelo) {
if($modelo) {
require_once('models.php');
$data = new $modelo();
settype($data, 'array');
return $data;
}
#las
modificaciones al modelo se harían aquí
}
Tercer paso: enviar la información a la vista
Finalmente, nuestro controlador, enviará la información obtenida del
modelo, a la vista.
Para hacerlo, utilizará una función donde preparará esta información
para al fin enviarla:
function
enviar_data() {
$vista
= capturar_evento();
if($vista)
{
$modelo
= identificar_modelo($vista);
if($modelo)
{
$data
= invocar_modelo($modelo);
if($data) {
require_once('view.php');
render_data($vista,
$data);
}
}
}
}
El
controlador, solo deberá llamar a su propia función enviar_data() y la vista
automáticamente,
estará en condiciones de mostrar los resultados en pantalla al usuario:
enviar_data();
0 comentarios:
Publicar un comentario