El paradigma de la Programación Orientada a Objetos en PHP y el patrón de arquitectura de Software MVC (página 2)
Enviado por Eugenia Bahit
Por otro lado, por cuestiones de seguridad, se hacía necesario no permitir instanciar esta clase desde ningún lugar de la aplicación y controlar con mucha precaución, el acceso a sus métodos y propiedades, ya que una base de datos, es el "alma" de toda aplicación.
1.2 ¿Para qué declarar propiedades estáticas?
En principio, tanto el host como el usuario y contraseña de la base de datos, en esta aplicación, son únicos. No varían. De allí, que como característica se les asignó ser estáticos, a fin de, por cuestiones de seguridad, no puedan ser modificados dinámicamente (tengamos en cuenta que una clase abstracta debe ser heredada sí o sí para ser utilizada).
1.3 ¿Por qué propiedades estáticas y no constantes de clase?
Porque a las constantes, aunque lógicamente guardan en sí mismas la condición de "estáticas" en el sentido de que "no pueden ser modificadas", pueden ser accedidas desde cualquier clase que herede de la clase que las declare. Pues entonces, la pregunta es ¿Para qué querría una clase "hija" conocer el host, usuario y contraseña de una base de datos? Es una cuestión nétamente de seguridad, ya que a una constante no se la puede definir como privada y si se la quiere ocultar a las clases "hijas", no quedará otra alternativa que declararlas como propiedades estáticas.
1.4 ¿Por qué propiedades estáticas y a la vez privadas?
(ver respuestas anteriores)
1.5 ¿Con qué sentido declarar las propiedades como protegidas?
Es simple. Algunos módulos pueden necesitar utilizar una base de datos diferente. Todos los módulos, necesitarán queries personalizados para sus consultas. Y lógicamente, todos necesitarán acceder y conocer los resultados de los datos arrojados por una consulta. Es decir, que tanto la propiedad db_name como query y rows, deben tener permisos para ser leídas y modificadas, pero ¡Ojo! Solo por las clases hijas de DBAbstractModel ¿Qué sentido tendría permitir a un programador acceder a estas propiedades si puede ser la clase hija, quien las controle?
1.6 ¿Por qué los métodos open y close_connection son privados?
Pues porque la clase es la única con permiso para abrir y cerrar conexiones a la base de datos. Es una cuestión de control y seguridad. Si necesitas insertar datos, consultarlos o hacer con ellos otras actividades, tienes métodos protegidos pero no privados, que te permiten hacerlo.
1.7 ¿Por qué los métodos de consulta y ejecución son protegidos y no públicos?
Consultar una base de datos, modificar o eliminar sus datos, así como insertar nuevos, no puede ser una tarea que se deje librada al azar y al libre acceso de cualquiera. Es necesario "proteger" los datos a fin de resguardar su integridad y, la forma de hacerlo, es "proteger" los métodos que se encuentran al servicio de dichos datos.
1.8 ¿Por qué hay métodos declarados como abstractos y además protegidos?
Esta pregunta, en gran parte, la responde la respuesta de la pregunta 1.1. El hecho de que se definan como abstractos, es porque necesariamente DEBEN ser métodos comunes a toda clase que los hereden. Pero solo la clase hija, podrá definirlos (re-definirlos técnicamente hablando) ya que tal cual se explicó en la pregunta 1.1., solo ellas conocen los requerimientos específicos.
Se declaran además como protegidos, por una cuestión de seguridad ("por las dudas" para que solo puedan ser vistos por clases heredadas). Esto, da lugar a las clases hijas, a que modifiquen su visibilidad de acuerdo al criterio de cada una de ellas.
- 2. Respuestas a preguntas sobre la clase Usuario
2.1 ¿Por qué la clase Usuario es una extensión de DBAbstractModel?
La clase usuario TIENE necesariamente que heredar de DBAbstractModel ya que DEBE utilizar sus métodos (propios y definidos para acceder a la base de datos) y redefinir obligadamente aquellos declarados como abstractos, a fin de continuar un modelo de administración de los ABM (altas, bajas y modificaciones).
2.2 ¿Con qué fin nombre, apellido e e-mail son propiedades públicas mientras que clave es privada y id, protegida?
Pensemos esto como en la vida real: tu nombre, apellido e e-mail, puede ser necesario para cientos de "trámites" y acciones de tu vida diaria y no andas por la vida negándolos a todo quien te los pida. Podríamos decir, que no tiene nada de malo que facilites públicamente estos datos, a quien decidas.
Ahora bien ¿le das tu contraseña a cualquiera? Si lo haces, deja de hacerlo. La contraseña es un dato que debe ser privado. Nadie puede tener acceso a él. Es una cuestión de seguirdad.
El número de ID, sería como tu número de documento o pasaporte. Es un dato que debes mantener protegido pero que en algunos casos, te será requerido y necesitarás darlo obligadamente. Por ejemplo, no podrías negarte a mostrar tu pasaporte en migraciones. Sin embargo, DEBES negarte a decirle el PIN de tu tarjeta de crédito a cualquier persona.
2.3 ¿Por qué se utiliza el método __construct() para modificar el nombre de la base de datos? ¿Por qué no se encarga la clase madre de modificar ese valor?
El nombre de la base de datos, es algo que variará de acuerdo al módulo que lo esté trabajando. Seguramente, de existir en el futuro una clase llamada Producto, ésta, sobreescribirá el valor de db_name. Modificarlo automáticamente utilizando un cosntructor, nos asegura instanciar el objeto con un valor de propiedad adecuado.
2.4 ¿Por qué se utiliza require_once y no include_once?
La diferencia entre include y require es que require, si no puede incluir el archivo al que se está importando, frena la ejecución del script, siendo que include, solo arroja un error, pero continúa la ejecución. Al tratarse de una clase que "requiere" sí o sí, de su clase madre, no tendría sentido permitir que se continúe ejecutando, si no ha podido cargarse el archivo.
- 3. Respuestas a preguntas sobre el archivo de instancias
3.1 ¿Por qué el archivo tiene cuatro instancias al mismo objeto?
Es necesario hacer notar que si bien los objetos comparten propiedades y métodos en común, no todos son idénticos. Es decir, todos los seres humanos tenemos ciertas características en común y realizamos acciones similares. Pero cada uno de nosotros, tiene una única identidad. Por eso, no puede decirse que se instancia cuadro veces el mismo objeto, porque en realidad, son cuatro objetos diferentes donde cada uno de ellos, tiene una identidad propia.
CAPÍTULO III
Introducción al patrón Arquitectónico MVC
MVC, son las siglas de modelo-vista-controlador (o en inglés, model-view-controller), que es uno de los tantos patrones de arquitectura de software.
Antes de abordar de lleno este patrón, vamos a intentar hacer una introducción a la arquitectura de software, desmembrándola de lo general hacia lo particular, para al fin llegar al detalle, procurando entender exactamente de que se trata, en el contexto adecuado.
Probablemente, este capítulo sea el más complejo (y mucho más extenso en relación al Capítulo I). Pero si quieres poder aplicar de forma decuada el patrón MVC, debes hacer el esfuerzo de seguirlo con especial interés y actitud "entuciasta".
Introducción a la Arquitectura de Software
¿Qué es la arquitectura de software?
Es necesario aclarar, que no existe una definición única, exacta, abarcativa e inequívoca de "arquitectura de software". La bibliografía sobre el tema es tan extensa como la cantidad de definiciones que en ella se puede encontrar. Por lo tanto trataré, no de definir la arquitectura de software, sino más bien, de introducir a un concepto simple y sencillo que permita comprender el punto de vista desde el cual, este libro abarca a la arquitectura de software pero, sin ánimo de que ello represente "una definición más".
A grandes rasgos, puede decirse que "la Arquitectura de Software es la forma en la que se organizan los componentes de un sistema, interactúan y se relacionan entre sí y con el contexto, aplicando normas y principios de diseño y calidad, que fortalezcan y fomenten la usabilidad a la vez que dejan preparado el sistema, para su propia evolución".
Tal vez estés pensando "…al fin y al cabo, me haz dado una definición más…". La respuesta es sí. Probablemente no pude contenerme de hacerlo – no lo niego -. Pero, no debes tomar lo anterior como una definición, sino como la forma en la que en este libro, se abarca la arquitectura de software.
Tendencias de la Arquitectura de Software
Si bien no puede decirse o mejor dicho, no es muy académico decirlo, voy a tomarme el atrevimiento de mencionar solo dos tendencias arquitectónicas, claramente diferenciadas entre sí:
La Arquitectura de Software Orientada a Objetos (como "ingeniría" de sistemas)
La Arquitectura Estructurada (como "desarrollo" de una aplicación)
Como podemos ver, en este libro, es a la primera a la cual nos enfocamos.
A fin de satisfacer la inquietud de curiosos (y de paso, no ocultar que existen), voy a mencionar la existencia de otras dos corrientes: la arquitectura basada en patrones y la arquitectura basada en procesos y metodologías.
Personalmente, no las considero como cuatro corrientes ¿Por qué? Porque independientemente de cual te agrade más, si la AS orientada o objetos o la AS estructural, implican necesariamente dos corrientes que deben aplicarse de forma optativa (o utilizas una o la otra pero no las dos simultáneamente), mientras que la AS basada en patrones y la AS basada en procesos, pueden utilizarse como complemento de las dos primeras. Pero esto, es mera filosofía propia, con la cual, no he encontrado demasiado consenso. Pues no los aburriré con ello e iremos a lo práctico.
Características de la Arquitectura de Software: Atributos de calidad
La Calidad del Software puede definirse como los atributos implícitamente requeridos en un sistema que deben ser satisfechos. Cuando estos atributos son satisfechos, puede decirse (aunque en forma objetable), que la calidad del software es satisfactoria.
Estos atributos, se gestan desde la arquitectura de software que se emplea, ya sea cumpliendo con aquellos requeridos durante la ejecución del software, como con aquellos que forman parte del proceso de desarrollo de éste.
- Atributos de calidad que pueden observarse durante la ejecución del software
Disponibilidad de uso
Confidencialidad, puesto que se debe evitar el acceso no autorizado al sistema
Cumplimiento de la Funcionalidad requerida
Desempeño del sistema con respecto a factores tales como la capacidad de respuesta
Confiabilidad dada por la constancia operativa y permanente del sistema
Seguridad externa evitando la pérdida de información debido a errores del sistema
Seguridad interna siendo capaz de impedir ataques, usos no autorizados, etc.
- Atributos de calidad inherentes al proceso de desarrollo del software
Capacidad de Configurabilidad que el sistema otorga al usuario a fin de realizar ciertos cambios
Integrabilidad de los módulos independientes del sistema
Integridad de la información asociada
Capacidad de Interoperar con otros sistemas (interoperabilidad)
Capacidad de permitir ser Modificable a futuro (modificabilidad)
Ser fácilmente Mantenible (mantenibilidad)
Capacidad de Portabilidad, es decir que pueda ser ejecutado en diversos ambientes tanto de software como de hardware
Tener una estructura que facilite la Reusabilidad de la misma en futuros sistemas
Mantener un diseño arquitectónico Escalable que permita su ampliación (escalabilidad)
Facilidad de ser Sometido a Pruebas que aseguren que el sistema falla cuando es lo que se espera (testeabilidad)
De lo general a lo particular: del estilo arquitectónico al patrón de diseño
Existe una diferencia entre Estilo Arquitectónico, Patrón Arquitectónico y Patrón de Diseño, que debe marcarse a fin de evitar las grandes confusiones que inevitablemente, concluyen en el mal entendimiento y en los resultados poco satisfactorios. Éstos, son los que en definitiva, aportarán "calidad" al sistema resultante. En lo sucesivo, trataremos de establecer la diferencia entre estos tres conceptos, viendo como los mismos, se relacionan entre sí, formando parte de un todo: la arquitectura de software.
Relación y Diferencia
Estilo Arquitectónico, Patrón Arquitectónico y Patrón de Diseño, representan, de lo general a lo particular, los niveles de abstracción que componen la Arquitectura de Software. En este sentido, puede decirse que:
El Estilo Arquitectónico es el encargado de:
Describir la estructura general de un sistema, independientemente de otros estilos
Definir los componentes del sistema, su relación e interactividad
Ejemplos: flujo de datos, llamada y retorno, etc.
El Patrón Arquitectónico es el nivel en el cual la arquitectura de software:
Define la estructura básica de un sistema, pudiendo estar relacionado con otros patrones
Representa una plantilla de construcción que provee un conjunto de subsistemas aportando las normas para su organización
Ejemplos: Capas, MVC, Tuberías y Filtros, Pizarra, etc.
El Patrón de Diseño es el tercer nivel de abstracción de la arquitectura de software, cuya finalidad es la de precisar en detalle los subsistemas y componentes de la aplicación
Ejemplos: Proxy, Command, Factory, etc..
El Patrón Arquitectónico modelo-vista-controlador (MVC)
Habiendo dejado en claro de qué hablamos exactamente cuando nos referimos a "patrón arquitectónico", estamos en condiciones de ahondar en los detalles del patrón MVC.
Aclarciones previas
Antes de caer inmersos en el conocimiento sobre el patrón MVC, quiero dejar en claro que en este libro, no hará referencia a ningún framework.
El objetivo de POO y MVC en PHP no es el de formar a programadores en el uso de frameworks, sino que el mismo, parte de una clara pregunta ¿a caso los frameworks no han sido desarrollados por programadores? Tenemos la alternativa de utilizar frameworks para ahorrar tiempo de programación o, si realmente nos apasiona programar, adquirimos los conocimientos necesarios, tenemos la capacidad y nos animamos, podemos crear nuestros propios frameworks. De hecho, no se trata de reinventar la rueda, sino de crear una, adaptada a nuestras necesidades. Y si lo que necesitamos es una rueda para acoplar a un mueble que acabamos de crear ¿cuál sería el sentido de intentar modificar una rueda de camión si tenemos todas las herramientas necesarias para ser "creadores" y no "modificadores"?
Claro que esto, depende de la pasión, gusto, capacidad y por qué no, de la ambición de cada uno. El tiempo, es discutible. Pues puede demandarte más tiempo modificar algo que ya existe, que crearlo. Si quieres reparar un mueble te llevará más tiempo repararlo que ir a comprar uno nuevo. Y si eres ebanista, seguramente te llevará menos tiempo hacer un nuevo mueble que ir a comprarlo. Pues sabes exactamente lo que necesitas y como hacerlo y eso, hará que ahorres el tiempo de recorrer todas las mueblerías y termines comprando "el mueble que más se asemeje al que quieres". El mueble, será similar, pero no exactamente igual al que tu imaginaste. De todas formas, la alternativa de modificar, siempre la tienes… al igual que también tienes la de crear. Todo dependerá del criterio de elección que apliques y sea cual sea, tu elección será la correcta, justamente porque habrás "elegido" y eso, es lo más importante.
¿Qué es el patrón MVC?
El patrón MVC es un patrón de arquitectura de software encargado de separar la lógica de negocio de la interfaz del usuario y es el más utilizado en aplicaciones Web, ya que facilita la funcionalidad, mantenibilidad y escalabilidad del sistema, de forma simple y sencilla, a la vez que permite "no mezclar lenguajes de programación en el mismo código".
MVC divide las aplicaciones en tres niveles de abstracción:
Modelo: representa la lógica de negocios. Es el encargado de accesar de forma directa a los datos actuando como "intermediario" con la base de datos. Lo que en nuestro ejemplo de programación orientada a objetos, serían las clases DBAbstractModel y Usuario.
Vista: es la encargada de mostrar la información al usuario de forma gráfica y "humanamente legible".
Controlador: es el intermediario entre la vista y el modelo. Es quien controla las interacciones del usuario solicitando los datos al modelo y entregándolos a la vista para que ésta, lo presente al usuario, de forma "humanamente legible".
¿Cómo funciona el patrón MVC?
El funcionamiento básico del patrón MVC, puede resumirse en:
El usuario realiza una petición
El controlador captura el evento (puede hacerlo mediante un manejador de eventos – handler -, por ejemplo)
Hace la llamada al modelo/modelos correspondientes (por ejemplo, mediante una llamada de retorno – callback -) efectuando las modificaciones pertinentes sobre el modelo
El modelo será el encargado de interactuar con la base de datos, ya sea en forma directa, con una capa de abstracción para ello, un Web Service, etc. y retornará esta información al controlador
El controlador recibe la información y la envía a la vista
La vista, procesa esta información pudiendo hacerlo desde el enfoque que veremos en este libro, creando una capa de abstracción para la lógica (quien se encargará de procesar los datos) y otra para el diseño de la interfaz gráfica o GUI. La lógica de la vista, una vez procesados los datos, los "acomodará" en base al diseño de la GUI – layout – y los entregará al usuario de forma "humanamente legible".
Funcionamiento del patrón modelo-vista-controlador
Hasta quí, hemos hablado de estilos arquitectónicos, nos hemos introducido en uno de los patrones arquitectónicos (MVC) pero, en todo esto ¿en qué momento intervienen los patrones de diseño?
Es aquí donde debemos notar que éstos, intervienen en la forma en la que cada capa (modelo, vista y controlador), "diseña" su estructura. El controlador decidirá (aunque en realidad, nosotros lo haremos) si utilizará un handler para manejar los eventos del usuario. En ese caso, estaría optando por un patrón de diseño. Si para llamar al modelo, utiliza un callback, estaría utilizando otro, y así en lo sucesivo.
Personalmente, sugiero que, a no ser que se trate de sistemas realmente robustos y complejos, no se compliquen demasiado – por ahora – en "aplicar" todos y cada uno de los patrones de diseño que encuentren en el camino. La forma de hacerlo bien, es:
Sencillez y simplicidad
Fácil mantenibilidad
Practicidad para evolucionar
Si se tienen en cuenta estas tres premisas, el resultado de un código limpio, legible y fácil de interpretar para cualquier programador, estará 90% asegurado.
CAPÍTULO IV
El Patrón MVC en PHP
Para que el concepto de modelo-vista-controlador nos queda más claro, vamos a ir analizándolo con ejemplos concretos, en el lenguaje que impulsa este libro: PHP.
Al final de este capítulo, vamos a encontrar ejercicios prácticos de autoevaluación y luego, continuaremos transformando y ampliando nuestro primer ejemplo del Capítulo II, siguiendo el patrón arquitectónico MVC, con sus correspondientes comentarios y aclaraciones.
El modelo
Con respecto al modelo, no tenemos demasiada novedad. El modelo, no es más que el conjunto de clases con las que hemos trabajado hasta ahora, incluyendo entre ellas, la capa de abstracción de la base de datos.
Interfaces en PHP: un nuevo concepto para crear modelos
En esta etapa, podemos ampliar las referencias de PHP, incorporando un nuevo concepto: las interfaces.
El Manual Oficial de PHP describe las interfaces de la siguiente forma:
"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."[8][…]
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();
}
}
También podemos crear otra clase que implemente la interface:
class Alfajor implements Postre {
public function set_ingredientes() {
$this->ingredientes = array('Tapas de maizena' => 2,
'dulce de leche'=>'1 cda. sopera',
'coco rallado'=>'1 cdta. de te');
}
function __construct() {
$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.
- Lo que NO deben hacer las insterfaces
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
La vista
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".
A tal fin, divideremos la vista en dos sub-capas: la GUI propiamente dicha y su lógica.
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:
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<<b>html lang="es">
<<b>head>
<<b>meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Título de la Página}
<<b>meta name="title" content="{Título de la Página}">
<<b>meta name="keywords" content="{keywords}">
<<b>meta name="description" content="{descripción}">
</<b>head>
<<b>body>
<<b>div id="page">
<<b>div id="cab">
<<b>img alt="home page" src="img/logo.gif"></<b>a>
</<b>div>
<<b>div id="contenido">
<<b>h1>{Título de la Página}</<b>h1>
</<b>div>
</<b>div>
</<b>body>
</<b>html>
Como podemos ver, en la plantilla HTML solo hay código HTML. Para un diseñador, será una tarea sencilla.
Veremos en el siguiente paso, como la lógica de la vista, se encargará de reemplazar estos datos.
La Lógica de la Vista
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):
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<<b>html lang="es">
<<b>head>
<<b>meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<<b>meta name="title" content="POO y MVC en PHP">
<<b>meta name="keywords" content="poo, mvc, php, arquitectura de software">
<<b>meta name="description" content="El paradigma de la programación orientada a objetos con el
patrón arquitectónico MVC en PHP">
</<b>head>
<<b>body>
<<b>div id="page">
<<b>div id="cab">
<<b>img alt="home page" src="img/logo.gif"></<b>a>
</<b>div>
<<b>div id="contenido">
<<b>h1>POO y MVC en PHP</<b>h1>
</<b>div>
</<b>div>
</<b>body>
</<b>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:
A qué modelo / modelos invocar
Qué y cuáles propiedades o atributos del modelo/modelos modificar o parámetros deberá entregar a sus métodos
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
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<<b>html lang="es">
<<b>head>
<<b>meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</<b>head>
<<b>body>
<<b>div id="page">
<<b>p>El valor de la <<b>b>propiedad</<b>b> es <<b>b>{propiedad}</<b>b></<b>p>
</<b>div>
</<b>body>
</<b>html>
Template vista_2.html
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<<b>html lang="es">
<<b>head>
<<b>meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</<b>head>
<<b>body>
<<b>div id="page">
<<b>p>El valor de <<b>b>propiedad_1</<b>b> es <<b>b>{propiedad_1}</<b>b> mientras que el
de <<b>b>propiedad_2</<b>b> es <<b>b>{propiedad_2}</<b>b></<b>p>
</<b>div>
</<b>body>
</<b>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();
Si el usuario ingresara en la URL http://servidor/controller.php no verá nada en pantalla.
Si ingresara en http://servidor/controller.php?vista=vista_2 verá lo siguiente:
Ahora, es momento de auto-evaluar lo que hemos aprendido y luego, completar nuestro primer ejemplo para finalizar nuestro aprendizaje.
Ejercicios Prácticos
Veamos cuanto aprendimos sobre los capítulos III y IV.
Ejercicio Nº3: Conceptos de Arquitectura, MVC y PHP
3.1) ¿Qué es MVC?
a) Un patrón de diseño
b) Un patrón arquitectónico
c) Un paradigma de programación
d) Un estilo arquitectónico
3.2) ¿Cuál de las siguientes opciones, corresponde a atributos de calidad implícitos en la arquitectura de software?
a) Polimorfismo, herencia, encapsulamiento y disponibilidad
b) Herencia, abstracción, seguridad y aislamiento
c) Disponibilidad, funcionalidad, seguridad, interoperabilidad y portabilidad
d) Todas las anteriores
3.3) Indica V (verdadero) o F (falso) según corresponda
a) [ ] Un patrón arquitectónico es el encargado de describir la arquitectura general de un sistema
b) [ ] Un patrón arquitectónico representa una plantilla de construcción que provee un conjunto de subsistemas y su forma de organización
c) [ ] Estilo arquitectónico y patrón arquitectónico son dos niveles de abstracción diferentes de la arquitectura de software
d) [ ] En MVC, el modelo es un intermediario entre la vista y el controlador
e) [ ] En MVC el controlador es el encargado de capturar los eventos del usuario
f) [ ] En MVC es recomendable mezclar código PHP y HTML
g) [ ] Una interface en PHP es lo mismo que una clase abstracta
h) [ ] Las clases abstractas en PHP cuplen la misma función que las interfaces
i) [ ] Una interface solo debe declarar los métodos pero éstos, no deben estar codificados
j) [ ] Las propiedades declaradas en las interfaces deben tener visibilidad pública
3.4) ¿Cuál de las siguientes afirmaciones es verdadera?
a) Las interfaces no pueden definir propiedades
b) Todos los métodos declarados en una interface deben ser públicos
c) Las interfaces no pueden instanciarse porque no tienen referencias asociadas a objetos
d) Las interfaces no pueden tener métodos definidos con su algoritmo correspondiente
e) Todas las opciones son correctas
En MVC, el usuario realiza una petición y el _____________ captura el evento, identificando el _____________ al que debe invocar y al cual realizar las modificaciones. Luego, envía esta información a _____________.
Ejercicio Nº4: Revisando código
4.1) ¿Cuál de las siguientes declaraciones es incorrectas?
a) class Gaseosa extends Bebida implements Producto, BebidaSinAlcohol
b) class Gaseosa extends BebidaSinAlcohol, BebidaGasificada implements Bebida, Producto
d) class Gaseosa implements Bebida
4.2) ¿Cuál es el error del siguiente código?
interface Producto { }
class Producto implements Producto { }
a) La clase no puede tener el mismo nombre que la interface
b) Ni la clase ni la interface tienen código
c) No hay errores
4.3) ¿Cuál es el error en el siguiente código?
interface Producto { }
class Bebida extends Producto { }
a) Ni la clase ni la interface tienen código
b) Donde utiliza "extends" debería utilizar "implements"
c) No hay errores
Soluciones a los ejercicios 3 y 4
Ejercicio Nº3
Pregunta 3.1: respuesta b
Pregunta 3.2: respuesta c
Pregunta 3.3:
A | B | C | D | E | F | G | H | I | J | ||
Verdadera | X | X | X | X | |||||||
False | X | X | X | X | X | X |
Pregunta 3.4: respuesta e
Pregunta 3.5:
En MVC, el usuario realiza una petición y el controlador captura el evento, identificando el modelo al que debe invocar y al cual realizar las modificaciones. Luego, envía esta información a la vista.
Ejercicio Nº4
Pregunta 4.1: respuesta b
Pregunta 4.2: respuesta a
Pregunta 4.3: respuesta c
Programación Real Con el patrón MVC
Vamos a retormar ahora, nuestro ejemplo del ABM de usuarios que comenzamos a programar en el capítulo II. Procederemos a ampliarlo y adaptarlo, seguiendo la estructura del patrón MVC.
Nótese que los métodos respectivos han sido resumidos no encontrándose en éstos, extensos algoritmos de validación de datos. Se ejemplifica todo aquello que es relevante en la POO bajo el el patrón arquitectónico MVC.
Estructura de directorios
Ya estamos en una etapa más avanzada, donde no basta con crear archivos. Nuestro primer ejemplo de "programación real" del capítulo II, será ampliado; agregaremos más archivos y se hace necesario organizarlos de forma tal, que pueda respetarse la sencillez y los beneficios que el patrón MVC nos brinda.
Es necesario que tengamos en cuenta, que NO SIEMPRE la estructura y organización de directorios y archivos puede predecirse. Por el contrario, a medida que una aplicación avanza, SIEMPRE es recomendable refactorizar el código al mismo ritmo que el sistema evoluciona.
Por eso, no se debe tener miedo de comenzar programando con grandes estructuras de código y hasta incluso, por qué no, "desprolijas".
Piensa en cuando vas al supermercado. Realizas las compras de todo lo que necesitas y las llevas a tu casa en bolsas y generalmente, con la mercadería desorganizada. Pero tienes todo lo que necesitas. Una vez que lo tienes, comienzas a organizarlo. Guardarás los alimentos que requieran refrigeración, en la heladera; los congelados en el freezer; los artículos de tocador en tu WC; etc.
No se debe tener miedo de agilizar la arquitectura de software y pensarla adaptativamente. Y aquí, es donde debemos considerar, la metodología que utilizaremos para gestionar nuestro proyecto.
Una de las prácticas técnicas propuesta por Extreme Programming, nos induce a realizar una refactorización constante del código, algo que, desde mi punto de vista, nos dará mejores resultados a la hora de pensar una arquitectura adecuada.
La siguiente estructura de directorios que propondré para adaptar nuestro ejemplo, puede servir de punto de partida para la arquitectura de una aplicación compleja de gran robustez.
Comenzaremos entonces, por crear la siguiente estructura de directorios:
core: el propósito de este directorio, será almacenar todas aquellas clases, helpers, utils, decorators, etc, que puedan ser reutilizados en otros módulos de la aplicación (aquí solo crearemos el de usuarios), es decir, todo aquello que pueda ser considerado "núcleo" del sistema. site_media: será el directorio exclusivo para nuestros diseñadores. En él, organizadmente, nuestros diseñadores podrán trabajar libremente, creando los archivos estáticos que la aplicación requiera. usuarios: éste, será el directorio de nuestro módulo de usuarios. En él, almacenaremos los archivos correspondientes al modelo, la lógica de la vista y el controlador, exclusivos del módulo de usuarios. |
Bajo el supuesto de que los modelos DBAbstractModel y Usuario se conservan y, simplemente a modo de ejercicio ¿en qué directorio crees que se debería almacenar cada uno de estos dos modelos?
Archivos del Modelo
Los archivos de nuestro "modelo", serán ahora nuestros viejos db_abstract_model.php y usuarios_model.php a los cuales, haremos algunas modificaciones.
Archivo ./core/db_abstract_model.php
- Modificaciones incorporadas
Agregaremos la propiedad $mensaje, a fin de que el objeto, pueda comunicarse a través de mensajes con el resto de la aplicación.
El método execute_single_query() incorporará una validación que solo permitirá proceder con sus funciones, si recibe sus parámetros a través variables $_POST.
- Código fuente del archivo
Archivo ./usuarios/model.php
- Modificaciones incorporadas
El nombre del archivo cambia a model.php.
Se agrega una emisión de mensaje por cada acción concluyente de cada uno de los métodos
Sin influencia práctica, el método constructor aparece debajo de los métodos propios de la clase (una simple cuestión organizativa)
- Código fuente del archivo
Archivos de la Vista
En esta etapa, crearemos los archivos correspondientes a la GUI y su lógica.
Los primeros, serán los archivos que crearán nuestros diseñadores (5 archivos HTML y 1 archivo CSS, que se expondrán a modo práctico, sin ánimo de servir de ejemplo como interfaces gráficas).
La lógica de la vista, estará en nuestras manos.
Comencemos.
Archivos de la GUI
Recordemos que se trataba de un ABM de Usuarios, donde teníamos la posibilidad de:
Mostrar los datos de un usuario
Agregar un nuevo usuario
Modificar un usuario existente
Eliminar un usuario de la base de datos
Todos estos archivos, se almacenarán en nuestro directorio estático site_media.
Crearemos una plantilla HTML general, cuatro plantillas de formularios y un archivo CSS. Los 5 primeros se almacenarán en ./site_media/html/ con el prefijo usuario_ que identificará el módulo (también podrían almacenarse en un subdirectorio llamado usuario. Eso lo dejo a vuestra libre elección). El archivo CSS, lógicamente se almacenará en ./site_media/css/.
- Archivo ./site_media/html/usuario_template.html
(plantilla HTML general)
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<<b>html lang="es">
<<b>head>
<<b>meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</<b>head>
<<b>body>
<<b>div id="cabecera">
<<b>h1>Administrador de usuarios</<b>h1>
<<b>h2>{subtitulo}</<b>h2>
</<b>div>
<<b>div id="menu">
<<b>a href="/mvc/{VIEW_SET_USER}" title="Nuevo usuario">Agregar usuario</<b>a>
<<b>a href="/mvc/{VIEW_GET_USER}" title="Buscar usuario">Buscar/editar usuario</<b>a>
<<b>a href="/mvc/{VIEW_DELETE_USER}" title="Borrar usuario">Borrar usuario</<b>a>
</<b>div>
<<b>div id="mensaje">
{mensaje}
</<b>div>
<<b>div id="formulario">
{formulario}
</<b>div>
</<b>body>
</<b>html>
Por favor, obsérvese que en este archivo, se deberán reemplazar dinámicamente: el subtítulo del módulo (método), las URL de los enlaces de las vistas, el mensaje emitido por el sistema y el formulario correspondiente al método/vista solicitado por el usuario.
- Archivo ./site_media/html/usuario_agregar.html
(formulario para agregar un nuevo usuario)
<<b>form id="alta_usuario" action="{SET}" method="POST">
<<b>div class="item_requerid">E-mail</<b>div>
<<b>div class="form_requerid"><<b>input type="text" name="email"
id="email"></<b>div>
<<b>div class="item_requerid">Clave</<b>div>
<<b>div class="form_requerid"><<b>input type="password" name="clave"
id="clave"></<b>div>
<<b>div class="item_requerid">Nombre</<b>div>
<<b>div class="form_requerid"><<b>input type="text" name="nombre"
id="nombre"></<b>div>
<<b>div class="item_requerid">Apellido</<b>div>
<<b>div class="form_requerid"><<b>input type="text" name="apellido"
id="apellido"></<b>div>
<<b>div class="form_button"><<b>input type="submit" name="enviar"
id="enviar" value="Agregar"></<b>div>
</<b>form>
Nótese que este archivo no posee datos dinámicos que deban ser reemplazados.
- Archivo ./site_media/html/usuario_borrar.html
(formulario para eliminar un usuario identificado por su e-mail)
<<b>form id="alta_usuario" action="{DELETE}" method="POST">
<<b>div class="item_requerid">E-mail</<b>div>
<<b>div class="form_requerid"><<b>input type="text" name="email"
id="email"></<b>div>
<<b>div class="form_button"><<b>input type="submit" name="enviar"
id="enviar" value="Eliminar"></<b>div>
</<b>form>
Nótese que al igual que el archivo anterior, éste, tampoco contiene datos dinámicos que deban ser reemplazados.
- Archivo ./site_media/html/usuario_buscar.html
(archivo que permite buscar un usuario por su e-mail para luego mostrarlo en el formulario de edición, ya sea para editarlo o solo para ver sus datos)
<<b>form id="alta_usuario" action="{GET}" method="GET">
<<b>div class="item_requerid">E-mail</<b>div>
<<b>div class="form_requerid"><<b>input type="text" name="email"
id="email"></<b>div>
<<b>div class="form_button"><<b>input type="submit"
id="enviar" value="Buscar"></<b>div>
</<b>form>
Nótese que al igual que los dos archivos anteriores, éste, tampoco contiene datos dinámicos que deban ser reemplazados.
- Archivo ./site_media/html/usuario_modificar.html
(archivo para visualizar los datos de un usuario y modificarlos)
<<b>form id="alta_usuario" action="{EDIT}" method="POST">
<<b>div class="item_requerid">E-mail</<b>div>
<<b>div class="form_requerid"><<b>input type="text" name="email"
id="email" value="{email}" readonly></<b>div>
<<b>div class="item_requerid">Nombre</<b>div>
<<b>div class="form_requerid"><<b>input type="text" name="nombre"
id="nombre" value="{nombre}"></<b>div>
<<b>div class="item_requerid">Apellido</<b>div>
<<b>div class="form_requerid"><<b>input type="text" name="apellido"
id="apellido" value="{apellido}"></<b>div>
<<b>div class="form_button"><<b>input type="submit" name="enviar"
id="enviar" value="Guardar"></<b>div>
</<b>form>
Por favor, nótese que en este archivo deberán reemplazarse dinámicamente los datos del usuario en los campos de formulario correspondientes. Obsérvese que el campo "email" es de solo lectura.
- Archivo ./site_media/css/base_template.css
(hoja de estilos en cascada)
body {
margin: 0px 0px 0px 0px;
background-color: #ffffff;
color: #666666;
font-family: sans-serif;
font-size: 12px;
}
#cabecera {
padding: 6px 6px 8px 6px;
background-color: #6699FF;
color: #ffffff;
}
#cabecera h1, h2 {
margin: 0px 0px 0px 0px;
}
#menu {
background-color: #000000;
color: #ffffff;
padding: 4px 0px 4px 0px;
}
#menu a {
width: 100px;
background-color: #000000;
padding: 4px 8px 4px 8px;
color: #f4f4f4;
text-decoration: none;
font-size: 13px;
font-weight: bold;
}
#menu a:hover {
background-color: #6699FF;
color: #ffffff;
}
#mensaje {
margin: 20px;
border: 1px solid #990033;
background-color: #f4f4f4;
padding: 8px;
color: #990033;
font-size: 15px;
font-weight: bold;
text-align: justify;
}
#formulario {
margin: 0px 20px 10px 20px;
border: 1px solid #c0c0c0;
background-color: #f9f9f9;
padding: 8px;
text-align: left;
}
item_requerid {
width: 150px;
height: 22px;
padding-right: 4px;
font-weight: bold;
float: left;
clear: left;
text-align: right;
}
form_requerid {
height: 22px;
float: left;
clear: right;
}
input {
border: 1px solid #c0c0c0;
}
form_button {
padding-top: 15px;
margin-left: 154px;
clear: both;
}
#enviar {
padding: 5px 10px 5px 10px;
border: 2px solid #ffffff;
background-color: #000000;
color: #ffffff;
font-family: sans-serif;
font-size: 14px;
font-weight: bold;
cursor: pointer;
}
#enviar:hover {
background-color: #6699FF;
}
Archivo ./usuarios/view.php
Lógica de la vista
Por favor, nótese que este archivo, utiliza constantes. Las mismas, y a fin de otorgar mayor legibilidad y organización al código, serán definidas en un archivo independiente almacenado en ./usuarios/, llamado constants.php que será expuesto más adelante.
El controlador
Archivo ./usuarios/controller.php
Por favor, obsérvese que el controlador importa el archivo constants.php y utiliza constantes que serán definidas en dicho archivo (veremos éste más adelante).
Por otro lado, el handler del controlador, maneja las peticiones del usuario sobre la base de la URI detectada. Este ejemplo, maneja "URL amigables" (friendly url), que serán tratadas más adelante, configurando las mismas en el archivo .htaccess de la aplicación.
Archivos de configuración complementarios
Archivo ./usuarios/constants.php
Este archivo contiene todas las constantes del módulo y no se le debería agregar ningún dato que no fuese una constante.
Archivo .htaccess
Agregar al archivo .htaccess de la aplicación, las siguientes líneas:
RewriteEngine on
RewriteRule ^usuarios/ usuarios/controller.php
Nótese que dependiendo del directorio raíz de la aplicación, probablemente se deba modificar la línea RewriteRule ^usuarios/ usuarios/controller.php
Nota Final
Hemos llegado al final de este libro. Espero que todo lo aquí expuesto, les haya sido de utilidad y los invito a hacerme llegar sus dudas, sugerencias y comentarios através de mi e-mail o visitando la página del libro:
http://eugeniabahit.blogspot.com/2011/07/poo-y-mvc-en-php.html
¡Gracias por el tiempo que han dedicado!
¡Éxitos en tu carrera!
Autor:
Eugenia Bahit
AVISO LEGAL
"POO y MVC en PHP" de Eugenia Bahit se distribuye bajo una Licencia Creative Commons Atribución-NoComercial-SinDerivadas 3.0 Unported.
Usted es libre de:
Compartir, copiar, distribuir, ejecutar y comunicar públicamente la obra.
Bajo las condiciones siguientes:
Atribución. Debe reconocer los créditos de la obra de la manera especificada por el autor o el licenciante (pero no de una manera que sugiera que tiene su apoyo o que apoyan el uso que hace de su obra).
No Comercial. No puede utilizar esta obra para fines comerciales.
Sin Obras Derivadas. No se puede alterar, transformar o generar una obra derivada a partir de esta obra.
[1] http://www.maestrosdelweb.com/
[2] tunait nos ofrece una de las mejores colecciones de códigos JavaScript, en su sitio Web http://tunait.com/javascript/
[3] http://www.desarrolloweb.com Portal de desarrollo Web y programación, de la comunidad hispanoparlante
[4] Este libro ha sido editado utilizando OpenOffice Writer 3.2 con el plug-in COOoder para el coloreado de sintaxis
[5] Fuente de la cita: http://php.net/manual/es/keyword.class.php
[6] Fuente de la cita: http://www.php.net/manual/es/language.oop5.basic.php
[7] Fuente de la cita: http://www.php.net/manual/es/language.oop5.abstract.php
[8] Fuente de la cita: http://php.net/manual/es/language.oop5.interfaces.php
Página anterior | Volver al principio del trabajo | Página siguiente |