martes, 11 de febrero de 2014

Diseñando nuestro portal

El diseño puede llegar a ser fustrante sobretodo cuando todos los esfuerzos se centran en la programación. En mi opinión es preferible separar ambos mundos: la programación y el diseño. Es común tener una apariencia estándar del portal, para ello el uso de plantillas (skins) nos permitirá separar la representación de la lógica de la aplicación.
Primero definiremos un esqueleto genérico para nuestro portal, en nuestro caso un patrón de dos columnas con cabecera y pie, y una sección destinada a un menú rápido. He tomado como ejemplo las múltiples plantillas gratuitas que circulan por Internet, concretamente la usada aquí puede encontrarse en http://www.maxdesign.com.au/articles/css-layouts/two-liquid/

Seguiremos los siguientes pasos:
  • Header: Cabecera del portal, logo, motor de búsqueda, etc.
  • Navigation: Menú de acceso rápido.
  • Aside: Menú lateral de usuario.
  • Main Content: Contenido del portal.
  • Footer: Pie del portal, contacto, copyright, etc.
Para ello:
  1. Crearemos una carpeta nueva en el directorio application llamada layouts.
  2. En la nueva carpeta creada añadiremos una subcarpeta llamada scripts.
  3. Crearemos el fichero layout.phtml en application/layouts/scripts.
  4. Crearemos una carpeta llamada css en public.
  5. Crearemos una carpeta llamada images en public, donde depositaremos el fondo de la columna derecha.
Contenido del fichero application/layouts/scripts/layout.phtml
<?php
echo $this->doctype ();
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<?php
echo $this->headTitle ();
echo $this->headScript ();
// add a link to the site style sheet
$this->headLink ()->appendStylesheet ( '/css/layout.css' );
echo $this->headLink ();
?>
</head>
<body>
 <div id="container">
  <div id="header">
   <h1>Zend Framework CMS</h1>
  </div>
  <div id="navigation">
  <?php echo $this->layout()->nav;?>
 </div>
  <div id="content-container">
   <div id="content">
   <?php echo $this->layout()->content?>
  </div>
   <div id="aside">
   <?php echo $this->layout()->subNav;?> 
  </div>
   <div id="footer">
    <em>Powered by the Zend Framework</em>
   </div>
  </div>
 </div>
</body>
</html>
Contenido del fichero public/css/layout.css:

@CHARSET "ISO-8859-1";

#container {
 margin: 0 auto;
 width: 100%;
 background: #fff;
}

#header {
 background: #ccc;
 padding: 20px;
}

#header h1 {
 margin: 0;
}

#navigation {
 float: left;
 width: 100%;
 background: #333;
}

#navigation ul {
 margin: 0;
 padding: 0;
}

#navigation ul li {
 list-style-type: none;
 display: inline;
}

#navigation li a {
 display: block;
 float: left;
 padding: 5px 10px;
 color: #fff;
 text-decoration: none;
 border-right: 1px solid #fff;
}

#navigation li a:hover {
 background: #383;
}

#content-container {
 float: left;
 width: 100%;
 background: #FFF url(/images/layout-two-liquid-background.gif) repeat-y 68% 0;
}

#content {
 clear: left;
 float: left;
 width: 60%;
 padding: 20px 0;
 margin: 0 0 0 4%;
 display: inline;
}

#content h2 {
 margin: 0;
}

#aside {
 float: right;
 width: 26%;
 padding: 20px 0;
 margin: 0 3% 0 0;
 display: inline;
}

#aside h3 {
 margin: 0;
}

#footer {
 clear: left;
 background: #ccc;
 text-align: right;
 padding: 20px;
 height: 1%;
}

Hemos de incluir el directorio de layouts creado en nuestro fichero de configuración para que la aplicación cargue sus contenidos. Para ello editamos application/configs/application.ini y añadimos en la sección production la entrada :

resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"

Para finalizar sustituiremos el contenido del portal por un texto más simple. Para ello editaremos el fichero application/views/scripts/index/index.phtml con el siguiente código:
<h2>Home</h2>
<p>Esta es la página Home por defecto...</p>

Podemos probar el resultado navegando en http://localhost:


Filosofía de ZendFramework

Zend Framework son un conjunto de librerías para el desarrollo de aplicaciones PHP creadas por al empresa Zend. Zend está detrás de Zend Framework pero son muchas más las empresas que han aportado para que este proyecto evolucione y tenga una continuidad en el tiempo.
Zend Framework se basa en una arquitectura Modelo-Vista-Controlador.



  • Modelo: Ofrece una capa de abstracción sobre los datos de nuestra aplicación, aporta las funcionalidades básicas de rutinas de acceso a los datos.
  • Vista: Es la encargada de la representación de los datos de la capa Modelo, es la encargada de aportar las funcionalidades básicas de interacción de los usuarios y nuestra aplicación.
  • Controlador: Es el encargado de gestionar las peticiones de interacción con nuestras vistas y el árbitro que gestiona el flujo de datos de nuestra aplicación.
A grandes rasgos podemos decir que cada modelo que define nuestra lógica de la aplicación tendrá un controlador asociado, el cual nos definirá las posibles acciones que sobre el modelo de datos se podrá interaccionar, así como las diferentes vistas en forma de HTML que tendrá como resultado la ejecución de las acciones del controlador.

La arquitectura de directorios básica de Zend Framework tiene como elementos principales:
  • application: es donde tendremos ubicados todos los elementos de la arquitectura Modelo-Vista-Controlador. Dentro encontraremos las carpetas models, views y controllers, correspondientes a la ubicación de los modelos, vistas y controladores. Además en application encontraremos la carpeta configs donde definiremos los parámetros de configuración de la aplicación.
  • docs: Destinado a la documentación de nuestra aplicación.
  • library: En esta carpeta irá el código de nuestras librerías, eso incluye si se desea Zend Framework, aunque es más flexible tener Zend Framework en una ubicación común a todas las aplicaciones y definir su ruta en el include_path del php.ini.
  • public: Carpeta donde irán ubicados todos los archivos requeridos por el servidor al servir las vistas, tales como ficheros css, imágenes, etc.
  • test: Directorio destinado a los scripts de prueba, pueden escribirse a mano, test PHPUnit, etc.
Cabe destacar dentro del directorio public el archivo index.php, es el encargado de iniciar toda la aplicación instanciando un objeto del tipo Zend_Application y lanzando el método run de la clase Bootstrap.
La clase Bootstrap está en la raíz del directorio application, en el fichero Bootstrap.php, su propósito es inicializar la aplicación, ajustar las preferencias del entorno (la zona horaria, el nivel del error_reporting, etc), además de otros ajustes específicos al procesamiento que hace la aplicación de las vistas como por ejemplo la codificación.



Integración con Zend Studio Client

Ahora que ya hemos creado nuestro proyecto vamos a integrarlo con nuestro entorno de desarrollo. Yo personalmente uso Zend Studio Client, y en esta entrada explicaré como integrarlo con nuestro proyecto ya creado.

En Zend Studio Client seleccionamos del menú File -> New -> PHP Project from Existing Directory.
Inmediatamente nos mostrará un cuadro de diálogo para especificar el nombre del proyecto, en nuestro caso CeDocCMS, que es el nombre de la carpeta creada anteriormente. Recordemos que el proyecto se creó en la carpeta C:\Zend\Apache2\htdocs



Al especificar el proyecto seleccionaremos "Detect Local" para que sea el mismo Studio Client quien interaccione con nuestro servidor local.

 Al detectar la instalación local de nuestro ZendServer nos solicitará contraseña de administrador.


Al finalizar la instalación podemos seleccionar los paquetes de librerías que añadiremos, este es un paso opcional que más adelante pueden ser añadidas.


Finalmente disponemos de nuestro proyecto para trabajar con él desde Zend Studio.


Zend Server - Creando el proyecto

La elección de la carpeta destino de nuestro proyecto depende de nuestros gustos, más adelante definiremos un host vitual en la configuración de Apache para acceder a nuestro portal, así que en principio no nos debe preocupar mucho. Si trabajamos con un IDE como Zend Studio Client al hacer una distribución del proyecto (Deploy) o una depuración veremos que Zend Server usará unas carpetas diferentes.
Así pues nuestros proyectos los prodemos ubicar en la carpeta C:\Zend\Apache\htdocs.
Nota: Podemos escoger nuestra carpeta de proyectos "workspace", yo es la que suelo utilizar, principalmente porque la carpeta htdocs ubicaré otros portales ajenos a Zend como por ejemplo phpMyAdmin, y así no mezclar nuestros proyectos con otros portales. Para mayor comodidad en las rutas del proyecto de aquí en adelante usaré htdocs.

Hay varias formas de crear un proyecto. Si hemos instalado ZendServer es tan sencillo como desde línea de comandos, estando en la carpeta de proyectos ejecutar la herramienta de Zend (Zend Tool Framework):
zf create project prueba

El desarrollo de aplicaciones en Zend se basa en el uso de las librerías de ZendFramework, en el caso de tener instalado ZendServer el sistema ya tiene una referencia a las carpetas de las librerías de ZendFramework, ubicadas en C:\Zend\ZendServer\share\ZendFramework, debemos tener configurada la la variable include_path con ruta de las librerías en nuestro php.ini
include_path=".;c:\Zend\ZendServer\bin\pear;C:\Zend\ZendServer\share\ZendFramework\library"
Otra opción es descargarse las librerías de Zend y copiarlas directamente en la carpeta library de nuestro proyecto.

Para más información consultar Create Your Project.

Para nuestro proyecto usaremos la herramienta antes mencionada zf.bat de ZendServer, que nos creará automáticamente la estructura de directorios para nuestro proyecto CeDocCMS:

C:\Zend\Apache\htdocs>zf create project CeDocCMS

Vemos que al ejecutar el comando se ha creado la siguiente estructura de directorios:

CeDocCMS
|-- application 
|   |-- Bootstrap.php
|   |-- configs
|   |   `-- application.ini
|   |-- controllers
|   |   |-- ErrorController.php
|   |   `-- IndexController.php
|   |-- models
|   `-- views
|       |-- helpers
|       `-- scripts
|           |-- error
|           |   `-- error.phtml
|           `-- index
|               `-- index.phtml
|-- library
|-- public
|   |-- .htaccess
|   `-- index.php
`-- tests
    |-- application
    |   `-- bootstrap.php
    |-- library
    |   `-- bootstrap.php
    `-- phpunit.xml

Ahora crearemos un host virtual en Apache que apunte a nuestro proyecto. El fichero donde definiremos nuestros hosts virtuales será conf/extra/httpd-vhosts.conf, pero antes será necesario incluir dicho fichero en la configuración de Apache para que lo tenga en cuenta.
Editaremos C:\Zend\Apache2\conf\httpd.conf y quitaremos los comentarios a la línea donde está definido httpd-vhosts.conf.
# Virtual hosts
Include conf/extra/httpd-vhosts.conf
En el fichero de hosts virtuales añadiremos la entrada de nuestro hosts.
Nota: Hemos de editar el fichero httpd-vhosts.conf puesto que hay hosts virtuales de ejemplo que hemos de eliminar.
Nota: Al crear nuestro proyecto con la Zend Tool Framework en el directorio C:\Zend\Apache2\htdocs\CeDocCMS\docs tenemos a nuestra disposición el fichero README.txt con la definición de ejemplo de nuestro hosts virtual.

<VirtualHost *:80>
   DocumentRoot "C:/Zend/Apache2/htdocs/CeDocCMS/public"
   ServerName .local

   # This should be omitted in the production environment
   SetEnv APPLICATION_ENV development   ErrorLog "logs/CeDodCMS.example.com-error.log"
   CustomLog "logs/CeDodCMS.example.com-access.log" common

   <Directory "C:/Zend/Apache2/htdocs/CeDocCMS/public">
       Options Indexes MultiViews FollowSymLinks
       AllowOverride All
       Order allow,deny
       Allow from all
   </Directory>

</VirtualHost>
Nota: Añadiremos al ejemplo del README.txt la definición personalizada de la generación de logs.

Reiniciaremos el servidor para aplicar los cambios realizados. Si ahora consultamos nuestro localhost veremos el proyecto en funcionamiento:



lunes, 10 de febrero de 2014

Zend - Ultimando la instalación de Zend Server

Para finalizar la instalación del servidor es conveniente instalar PEAR. Para ello desde la línea de comandos podemos ejecutar:

c:\>cd c:\Zend\ZendServer\bin
c:\Zend\ZendServer\bin>go-pear.bat


Pulsaremos Enter y seleccionaremos todos los directorios por defecto.
Nota: Nos añadirá una entrada en nuestro archivo php.ini con el directorio del PEAR.

;***** Added by go-pear

include_path=".;c:\Zend\ZendServer\bin\pear;C:\Zend\ZendServer\share\ZendFramework\library"

;*****
Ahora podemos instalar PHPUnit
c:\Zend\ZendServer\bin>cd pear
C:\Zend\ZendServer\bin\PEAR>pear config-set auto_discover 1
Mostrará un mensaje del estilo "config-set succeeded". Seguidamente ejecutamos la instalación de PHPUnit:
C:\Zend\ZendServer\bin\PEAR>pear install pear.phpunit.de/PHPUnit

Nota: En algunas circunstancias valora la posibilidad de reinicar el equipo para que los cambios surgan efecto. En el caso de Zend Server es posible que muestro un error de configuración en la variable include_path, dado que reconoce que su valor difiere del que tiene almacenado. El mensaje podría tener la siguiente forma:
The directive 'include_path' is mismatched: expected '".;C:\Zend\ZendServer\share\ZendFramework\library"', actual '".;c:\Zend\ZendServer\bin\pear;C:\Zend\ZendServer\share\ZendFramework\library"'

Aplicaríamos cambios y reiniciaríamos el servidor Zend.

Zend - Primeros pasos

Todo proyecto informático nace de una necesidad, en concreto la mía es hacer una pequeña aplicación en PHP para la creación de un inventario para una biblioteca, y para ello me serviré de ZendFrameWork.

Consideraciones previas

En estos ejemplos usaré una instalación fresca de ZendServer y como IDE de desarrollo ZendStudio 10.6. Todos los ejemplos están hechos en una máquina Windows, más adelante abordaré la carga del código en una máquina de producción Linux.
En el primer caso no es necesario que exista pues con el esqueleto de Zend FrameWork sería suficiente y en el caso del IDE es a gusto del consumidor.
ZendServer se ha instalado en la raíz del sistema, así que su ruta de acceso es "C:\Zend", así pues todos los proyectos estarán ubicados en "c:\Zend\Apache2\htdocs".

Empezando

Instalación de ZendServer. Para descargarlo es necesario tener un usuario registrado en http://www.zend.com/en/downloads/, allí seleccionaremos Zend Server. En el momento de escribir esta entrada la versión de Zend Server era 6.2.0. La versión de PHP es a gusto del usuario, yo instalé la 5.4
Nota: Sería recomendable instalar también MySQL

La primera pantalla es la de bienvenida:

La segunda hace referencia a la licencia, aceptamos si estamos de acuerdo y proseguimos.
 En la tercera pantalla elegiremos la opción "custom":

En la siguiente pantalla buscaremos la opción de instalación de MySQL Server y lo seleccionaremos:

Nota: podría ser interesante añadir más productos como por ejemplo IBM DB2 RTCL para acceder a sistemas iSeries.
En la siguiente pantalla seleccionaremos el path de instalación, para hacerlo más cómo ubicaremos a Zend Server en la raíz.

La siguiente pantalla nos pide los puertos de escucha para el servicio de páginas web y la administración del servidor. Atención si en nuestra máquina ya existen servidores web que usen esos puertos, quizás el puerto 80 debamos cambiarlo por 10080.

Instalación final pulsamos "Install":

Al finalizar la instalación nos permitirá ejecutar el servidor instalado, a lo cual respondemos que sí seleccionando la opción, inmediatamente nos abrirá un navegador con la url del servidor. Aceptaremos el contrato de licencia si estamos de acuerdo.
En la siguiente pantalla decidiremos si nuestro servidor será de desarrollo o producción, en mi caso fundamentalmente será desarrollo.
En la siguiente pantalla se nos solicita las contraseñas.

Finalmente si la instalación ha ido correctamente podremos ver el resultado:
Si consultamos el localhost ahora aparecerá la página de inicio de ZendServer:

martes, 13 de noviembre de 2012

Juli, Pupi, Pat y Pott


Imaginemos que en nuestro nuevo fichero físico tenemos los siguientes datos:
Figura 1: Listado del contenido de EMPREC.


Queremos listar la cantidad de horas del departamento 501.
 Sencillamente lo que haremos será buscar si hay registros correspondientes al departamento 501 y posteriormente (en caso de que los haya) los sumaremos.

Primer problema que nos encontramos es no disponer de los registros ordenados por la clave del departamento, bueno, para todo problema puede haber una solución, crearemos una vista de los datos o lo que es lo mismo: un fichero lógico. eso nos permitirá hablar de ellos.

Para ello crearemos nuestro fichero lógico con la sentencia:

STRSEU SRCFILE(MYLIB/QDDSSRC) SCRMBR(Nombre_Fichero_Lócigo) TYPE(LF) TEXT('Vista particular').

Si EMPREC era el fichero físico el lógico lo bautizaremos como EMPRECL.

Figura 2: Creación de la vista particular de EMPREC llamada EMPRECL.

Editaremos el código y añadiremos las claves de ordenación:

 Figura 3: Definición de la vistapara EMPRECL.

Para compilarlo utilizaremos la instrucción:
CRTLF FILE(MYLIB/EMPRECL) SRCFILE(MYLIB/QDDSSRC) SRCMBR(EMPRECL)

Nota: tengamos la precaución de tener en la lista de librerías MYLIB, para ello usar el comando EDTLIBL.
  
Crearemos nuestro primer fichero IL RPG con la instrucción:
STRSEU SRCFILE(MYLIB/QRPGLESRC) SRCMBR(EMPRPT) TYPE(RPGLE) OPTION(2)

Entraremos el siguiente código:
FEMPRECL   IF   E             DISK    RENAME(EMPREC:File)
D  Res            S              4B 0 INZ(0)
C     *START        SETLL     EMPRECL
C                   READ      File                                   71
C     *IN71         DOWEQ     *OFF
C                   IF        EDEPT = 501
C                   ADD       ENHRS         Res
C                   ENDIF
C                   READ      File                                   71
C                   ENDDO
* Fin de programa
C                   EVAL      *INLR = '1'

La primera línea del código es la definición del fichero lógico EMPRECL, cabe destacar que hay que renombrarlo para más tarde poder utilizarlo, sino el compilador generará un error.
La segunda línea corresponde a una declaración de variable local binaria de 4 posiciones.
La siguiente estructura corresponde a una iteración entre los datos del programa en forma de bucle Do While.
A esta forma de programación se la llama ILE RPG en formato fijo.

Ahora en cambio observemos este listado:
     FEMPRECL   IF   E             DISK
     D  Res            S              4B 0 INZ(0)
      /FREE
       setll *START EMPRECL;
       read EMPRECL;
       dow not %eof(EMPRECL);
         if EDEPT = 501;
           Res = Res + ENHRS;
         endif;
         read EMPRECL;
       enddo;
       // Fin de programa
       *INLR = *on;
      /END-FREE  

Es el mismo programa pero con notación libre. A diferencia del anterior de formato fijo el libre el código encerrado entre las cláusulas /FREE y /END-FREE, eso sí, se ha de tener la precaución de finalizar cada linea con un ";".
En programación fija cada sentencia tiene una posición que ha de respetarse, para programadores que provienen de lenguajes como el C, C++, java, PHP y otros de alto nivel se hace muy costoso y difícil de comprender, además, heredado de anteriores versiones de RPG los programadores tienen la tendencia de usar del GOTO rompiendo las bases de la programación estructurada.

Ahora una tercera versión del mismo código:

     D  Res            S              4B 0 INZ(0)
     C/EXEC SQL
     C+  SELECT SUM(ENHRS) INTO :Res
     C+    FROM EMPRECL
     C+    WHERE EDEPT=501
     c/end-exec
       // Fin de programa
     C                   EVAL      *INLR = '1'  


¡Podemos usar sentencias SQL!

La forma de compilar este código es diferente, ejecutaremos:
CRTSQLRPGI OBJ(MYLIB/EMPRPT) SRCFILE(MYLIB/QRPGLESRC) COMMIT(*NONE)
Opcionalmente añadiremos la depuración de código fuente DBGVIEW(*SOURCE).
Podemos crear el fichero para ser editado con la instrucción:
STRSEU SRCFILE(MYLIB/QRPGLESRC) SRCMBR(Nombre_Fichero) TYPE(SQLRPGLE) OPTION(2)

Queda a elección del programador usar un tipo y otro, yo personalmente prefiero el formato libre, y si puedo añadir sentencias SQL... mejor que mejor.