martes, 30 de diciembre de 2008

Tags Libraries

Biblioteca de Etiquetas en Java

jueves, 25 de septiembre de 2008

Postgis la extension espacial de postgres

miércoles, 24 de septiembre de 2008

Validar login de usuario de base de datos Postgres

Tratando validar el ingreso a mi aplicación mediante un script sql en postgre, publico lo siguiente


CREATE OR REPLACE FUNCTION sp_validloginpostgres
(
username character varying,
userpass character varying
)
RETURNS refcursor AS
$BODY$
/****************
* Descripcion : Obtiene un registro de la tabla pg_shadow, permitiendo validar la existencia de
* inicio de sesion valido de la base de datos de postgres.
* Fecha_Crea : -*-
* Fecha_Mod : -*-
* Parametros : userName : nombre de usuario de la base de datos de postgres.
* userPass : contraseña de usuario de la base de datos de postgres.
* Autor : Hugo P. Flores J.
* Version : Desarrollo.
****************/
DECLARE
p_userName ALIAS FOR $1;
p_userPass ALIAS FOR $2;
cursorLogin refcursor;
BEGIN
OPEN cursorLogin FOR SELECT usename,
passwd
FROM pg_shadow
WHERE( usename = p_userName AND
passwd = ( 'md5' || md5( p_userPass || p_userName ) )
);
RETURN cursorLogin;
END;$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
ALTER FUNCTION sp_validloginpostgres(character varying, character varying) OWNER TO postgres;

Como crear una Base de Datos en Postgres

Publico este manual para aquellos que les interese un poco sobre este motor de base de datos.

lunes, 15 de septiembre de 2008

miércoles, 16 de julio de 2008

Un poco de POO en PHP

miércoles, 2 de abril de 2008

Edicion 11 esta listo Full Circle

Una de las revistas interesantes que teratan temas sobre desarrollo, miscelanias, etc en Ubuntu.

Este mes:

  • Linux Mint versus Ubuntu.
  • How-To: TrueCrypt en Ubuntu, iPod Classic & Amarok, Introduccion a LaTeX y mas!
  • Revision de Lenovo 3000 C200 laptop ejecutando Ubuntu.
  • Cartas, Preguntas y respuestas, Mi Escritorio, Top 5 y mas!


Descargar versiones anteriores

lunes, 31 de marzo de 2008

Visita a la Sede de Google

Navegando por internet encontre este interesante informe de un canal argentino donde se muestra como es que viven la gente de google.

Primer informe:

domingo, 30 de marzo de 2008

Insertar un objeto java.sql.Date en SQL Server 2000

En ocasiones queremos saber como insertar un tipo de dato Date del paquete java.sql, normalmente para hacerlo realizamos una conversión CASTING en la sentencia SQL que se le manda a la base de datos, p.e

INSERT INTO ... VALUES(..., convert(varchar,DateColumn,103)...)

En el caso de que no deseamos realizar esa conversion, tenemos el siguiente código:

USE pubs
GO
CREATE TABLE test(test_varchar VARCHAR(255), test_date DATETIME)
GO


/*
* Main.java
*/

package testinsertdate;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
*
* @author hugo
*/
public class Main {

/** Creates a new instance of Main */
public Main() {
}

/**
* @param args the command line arguments
*/
public static void main(String[] args) throws ParseException {
int result = 0;
Connection con = null;
PreparedStatement ps = null;

SimpleDateFormat fecha = new SimpleDateFormat( "dd/MM/yyyy" );

try{
ConnectionFactory cf = new ConnectionFactory( ConnectionFactory.TYPE_MSSQL,
"localhost", "pubs" );
con = cf.getConnection( "sa", "sa" );
ps = con.prepareStatement( "INSERT INTO test VALUES( ?, ? )" );
ps.setString( 1, "test2" );
ps.setDate( 2, new Date( fecha.parse( "15/02/1982" ).getTime() ) );

ps.executeUpdate();
System.out.println( "Conversion sin excepcion!" );
}catch( SQLException sqle ){
sqle.printStackTrace();
}catch( ParseException pe){
pe.printStackTrace();
}finally{
if( ps != null ) ConnectionFactory.close(ps);
if( con != null ) ConnectionFactory.close(con);
}
}
}
Enlaces de interes:
La clase ConnectionFactory ya lo vimos en el el Post de Conexión con SQL Server 2005
Saludos a todos ;)

VT de PHP y MySQL

Esta es una de las primeros videos tutoriales que iré introduciendo en este blog sobre php y otras tecnologías :)

FileUpload Subida de ficheros al servidor

Descargar ficheros es sumamente sencillo desde el servidor, el problema surge cuando queremos subirlos, los JSP y Servlets de Java no tienen mecanismos para poder manejar la subida de ficheros desde formularios, siendo un problema tratar de extraer el contenido desde HTTP request. Una mejor opcion que nos puede ayudar es utilizar librerias de terceros.

Existe una robusta libreria open-source diseñada para este propósito del paquete
Apache Jakarta Commons FileUpload.

Requerimientos

  • Descargar la libreria Jakarta Commons FileUpload 1.2.1: commons-fileupload-1.2.1.jar
  • Ademas de esta libreria necesitaremos otra de complemento interno de Commons FileUpload llamada Jakarta Commons IO librarie: commons-io-1.4.jar. En este articulo se asume que usted esta utilizando estas librerias.
Software de prueba

El código ha sido probado en un entorno de Java EE5 con Tomcat 5.5.17.

Instalando Apache Jakarta Commons FileUpload y IO en el contenedor como Tomcat

El proximo paso es copiar los archivos jar en el directorio $CATALINA_HOME/webapps/NameProyect/WEB-INF/lib de su aplicación.


Diseñar el formulario


Para subir los ficheros al servidor debemos de crear un formulario un poco especial de tipo POST y MultiPart y que la peticion la dirija a un Servlet: subir.jsp
<form method="POST" enctype="multipart/form-data"
action="<%= request.getContextPath()%>/UploadFile">
Por favor, seleccione el trayecto del fichero a cargar
<br><input type="file" name="fichero">
<input type="submit">
</form>


getContextPatch() obtiene la ruta de su aplicación es este caso "/NameProyect"
Figura 1: formulario JSP para subir un archivo al servidor

Creando nuestro Servlet
Ahora hay que crear el Servlet bajo el nombre de UploadFile.java donde se mostará la forma básica de subir ficheros y como configurar algunos aspectos de la subida para un mejor control, como p.e el limitar el tamaño del fichero:
package servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.File;

import java.util.List;
import java.util.Iterator;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


/**
*
* @author hugo
* @version
*/
public class UploadFile extends HttpServlet {

private String dirUploadFiles; //directorio donde se guardara los archivos


protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();

// 1. obtengo el directorio donde guardare los archivos, desde un parametro de
// contexto en el archivo web.xml
dirUploadFiles = getServletContext().getRealPath( getServletContext().getInitParameter( "dirUploadFiles" ) );

// 2. Si la peticion es de tipo multi-part,
// static boolean isMultipartContent() devuelve true/false
if( ServletFileUpload.isMultipartContent( request ) ){

// 3. crear el arhivo factory
// DiskFileItemfactory es una implementacion de FileItemfactory
// esta implementacion crea una instacia de FileItem que guarda su
// contenido ya sea en la memoria, para elementos pequeños,
// o en un archivo temporal en el disco, para los
// elementos de mayor tamaño
FileItemFactory factory = new DiskFileItemFactory();


// 4. crear el servlet upload
// es un API de alto nivel para procesar subida de archivos
// Por defecto la instancia de ServletFileUpload tiene los siguientes valores:
// * Size threshold = 10,240 bytes. Si el tamaño del archivo está por debajo del umbral,
// se almacenará en memoria. En otro caso se almacenara en un archivo temporal en disco.
// * Tamaño Maximo del cuerpo de la request HTTP = -1.
// El servidor aceptará cuerpos de request de cualquier tamaño.
// * Repository = Directorio que el sistema usa para archivos temporales.
// Se puede recuperar llamando a System.getProperty("java.io.tmpdir").
ServletFileUpload upload = new ServletFileUpload( factory );
/* 5. declaro listUploadFiles
* Contendrá una lista de items de archivo que son instancias de FileItem
* Un item de archivo puede contener un archivo para upload o un
* campo del formulario con la estructura simple nombre-valor
* (ejemplo: <input name="text_field" type="text" />)
*
* Podemos cambiar las opciones mediante setSizeThreshold() y setRespository()
de la clase DiskFileItemFactory y el
método setSizeMax() de la clase ServletFileUpload, por ejemplo:

DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
diskFileItemFactory.setSizeThreshold(40960); // bytes

File repositoryPath = new File("/temp");
diskFileItemFactory.setRepository(repositoryPath);

ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
servletFileUpload.setSizeMax(81920); // bytes

*
*/
// limito a 300 Kb el humbral del tamaño del archivo a subir
// Long.parseLong( getServletContext().getInitParameter( "maxFileSize" ) )
upload.setSizeMax( new Long( getServletContext().getInitParameter( "maxFileSize" ) ).longValue() ); // 1024 x 300 = 307200 bytes = 300 Kb

List listUploadFiles = null;
FileItem item = null;

try{
// 6. adquiere la lista de FileItem asociados a la peticion
listUploadFiles = upload.parseRequest( request );

/* 7. Iterar para obtener todos los FileItem
* vamos a trabajar con generalidad
* programaremos como si quisieramos leer todos los
* campos sean 'simples' o 'file'. Por ello iteramos
* sobre todos los FileItem que recibimos:
* Los parámetros simples los diferenciaremos de los parámetros 'file'
* por medio del método isFormField()
*/
Iterator it = listUploadFiles.iterator();
while( it.hasNext() ){
item = ( FileItem ) it.next();
// 8. evaluamos si el campo es de tipo file, para subir al servidor
if( !item.isFormField() ){
//9. verificamos si el archivo es > 0
if( item.getSize() > 0 ){
// 10. obtener el nombre del archivo
String nombre = item.getName();
// 11. obtener el tipo de archivo
// e. .jpg = "image/jpeg", .txt = "text/plain"
String tipo = item.getContentType();
// 12. obtener el tamaño del archivo
long tamanio = item.getSize();
// 13. obtener la extension
String extension = nombre.substring( nombre.lastIndexOf( "." ) );

out.println( "Nombre: " + nombre + "<br>");
out.println( "Tipo: " + tipo + "<br>");
out.println( "Extension: " + extension + "<br>");
// 14. determinar si el caracter slash es de linux, o windows
//String slashType = ( nombre.lastIndexOf( "\\" ) > 0 ) ? "\\" : "/"; // Windows o Linux
// 15. obtener la ultima posicion del slash en el nombre del archivo
//int startIndex = nombre.lastIndexOf( slashType );
// 16. obtener el nombre del archivo ignorando la ruta completa
//String myArchivo = nombre.substring( startIndex + 1, nombre.length() );
// 17. Guardo archivo del cliente en servidor, con un nombre 'fijo' y la
// extensión que me manda el cliente,
// Create new File object
File archivo = new File( dirUploadFiles, nombre );

// 18. Write the uploaded file to the system
item.write( archivo );
if ( archivo.exists() ){
out.println( "GUARDADO " + archivo.getAbsolutePath() + "</p>");
}else{
// nunca se llega a ejecutar
out.println( "FALLO AL GUARDAR. NO EXISTE " + archivo.getAbsolutePath() + "</p>");
}

}
}
}

}catch( FileUploadException e ){
e.printStackTrace();
}catch (Exception e){
// poner respuesta = false; si existe alguna problema
e.printStackTrace();
}
}
out.println( "Fin de la operacion! ;)");
out.close();
}

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

}


Agreue la siguiente configuración al archivo web.xml:

<servlet>
<servlet-name>UploadFile</servlet-name>
<servlet-class>servlets.UploadFile</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadFile</servlet-name>
<url-pattern>/UploadFile</url-pattern>
</servlet-mapping>
<context-param>
<param-name>dirUploadFiles</param-name>
<param-value>/public/images/avatar</param-value>
</context-param>
<context-param>
<param-name>maxFileSize</param-name>
<param-value>307200</param-value>
</context-param>


Testeando:

Figura 2: Procesamiento de la subida de un fichero al servidor

Notas finales:

  1. Si el tamaño del fichero subido excede los 300 Kb, parametro que hemos configurado dentro de web.xml con el nombre de maxFileSize, no se mostrará ningun mensaje en pantalla luego de que el Servlet proceso la petición de subir el fichero, esto es debido a que detro del bloque try/catch del Servlet UploadFile.java se lanza una excepción del tipo FileUploadBase.FileSizeLimitExceededException por el método parseRequest(), para poder mejorar este comportamiento deberiamos crear un método por ejemplo processFormFiled() que procese la subida de un fichero desde un formulario y que devuelva true/flase como respuesta.
  2. Se puede mejorar la presentación del procesamiento de la subida del fichero mediante un progress bar utilizando Ajax.
Download source code


jueves, 28 de febrero de 2008

Accediendo a SQLServer2005 Express con JDBC - Parte 2 Configuraciones en Netbeans y creación de una clase ConnectionFactory para acceso a base de dato

En esta segunda entrega veremos en primer lugar la implementación de una clase que nos permitirá manejar las operaciones de conexiíon con SQL Server 2005 ( y con otras más):

package sqlserver2005;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


public class ConnectionFactory {
public final static int TYPE_MSSQL = 10;
public final static int TYPE_MYSQL = 20;
public final static int TYPE_ORACLE_10G_EX = 30;
public final static int TYPE_MSSQL2005 = 40;
private String driver;
private String url;

/**
* Constructor que carga el driver jdbc para poder trabajar con la base de datos
*
* @param typeDBMS tipo de base de datos a utilizar
* @param hostName IP o nombre del servidor de base de datos
* @param databaseName nombre de la base de datos con la que deseamos trabajar
*/
public ConnectionFactory( int typeDBMS, String hostName, String databaseName ) {
switch( typeDBMS ){
case 10:{ // Para SQL Server 2000
driver = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
url = "jdbc:microsoft:sqlserver://" + hostName + ":1433;DatabaseName=" +
databaseName;
break;
}
case 20:{ // Para MySQL 5.0
driver = "com.mysql.jdbc.Driver";
url = "jdbc:mysql://" + hostName + ":3306/" +
databaseName;
break;
}
case 30:{ // Para en Oracle 10g Express Edition
if( databaseName.equals( "" ) )
databaseName = "XE";
else
databaseName = "XE";
driver = "oracle.jdbc.driver.OracleDriver";
url = "jdbc:oracle:thin:@//" + hostName + ":1521/" + databaseName;
break;
}
case 40:{ // Para SQL Server 2005 Express Edition
driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
url = "jdbc:sqlserver://" + hostName + ":1433;DatabaseName=" +
databaseName;
break;
}
}
try{
// cargar la clase Driver
Class.forName( driver );
}catch( ClassNotFoundException cnfe ){
System.out.println( "Error: exception loading driver class" );
}
}

/**
* Devuelve un objeto de tipo Connection válido
*
* @param user usuario de la base de datos
* @param password clave del usuario de la base de datos
* @return Connection
*/
public Connection getConnection( String user, String password ) throws SQLException
{
return DriverManager.getConnection( url, user, password );
}// fin del metodo getConnection

/**
* Metodo para liberar recursos de memoria, cerrando la conextion con la base
* de datos
*
* @param con parametro de tipo Connection
*/
public static void close( Connection con ){
try{
con.close();
}catch( SQLException sqle ){
showMessageError( sqle );
}
}// fin del método closeConnection

/**
* Cierra un objeto ResultSet (Registros)
* @param con parametro de tipo ResultSet
*/
public static void close( ResultSet rs ){
try{
rs.close();
}catch( SQLException sqle ){
showMessageError( sqle );
}
}// fin del método closeConnection


/**
* Cierra un objeto Statement (Consulta)
* @param con parametro de tipo Statement
*/
public static void close( Statement stmt ){
try{
stmt.close();
}catch( SQLException sqle ){
showMessageError( sqle );
}
}// fin del método close

/**
* Cierra un objeto Statement (Consulta)
* @param con parametro de tipo Statement
*/
public static void close( PreparedStatement ps ){
try{
ps.close();
}catch( SQLException sqle ){
showMessageError( sqle );
}
}// fin del método close

/**
* Cierra un objeto Statement (Consulta)
* @param con parametro de tipo Statement
*/
public static void close( CallableStatement cs ){
try{
cs.close();
}catch( SQLException sqle ){
showMessageError( sqle );
}
}// fin del método close

/** muestra un mensaje de error en consolo, según sea el caso */
private static void showMessageError( SQLException sqle ){
System.out.println( "Error:" +
"\nmensaje: " + sqle.getMessage() +
"\nSQLState: " + sqle.getSQLState() +
"\nVencorCode: " + sqle.getErrorCode() + "\n" );
}// fin del método showMessageError
}


martes, 26 de febrero de 2008

Accediendo a SQLServer2005 Express con JDBC - Parte 1 Configuracion de SQL Server 2005 Express

Introduccion
En este tutorial veremos como conectarnos y mostrar datos de SQL Server 2005 Express con JDBC.

Todo esta dividido en 4 partes:

  1. Configuracion de SQL Server 2005 Express
  2. Configuraciones en Netbeans y creación de una clase ConnectionFactory para acceso a base de datos.
  3. Operaciones SQL
  4. Posibles problemas
Requerimientos:
  1. Microsoft SQL Server JDBC Driver
    La última version, visite Microsoft SQL Server 2005 JDBC Driver.
  2. NetBeans con JRE (Java Runtime Environment) version 1.5 o superior
    Puede encontrar en NetBeans.org.
Configuración paso a paso:
  • SQL Server 2005 Express
Por defecto SQL Server 2005 no permite conexiones remotas y esta deshabilitado ls cuenta sa, asi que nosotros tenemos que hacer los cambios respectivos de forma manual, si usted trata de conectarse se le mostrará un mensaje de error por ejemplo sea cual sea el nombre de su servidor:







Otro problema por defecto que puede surgir cuando queremos conectarnos es que las conexiones TCP/IP están deshabilidatas en SQL Server 2005 Express. Asi que JDBC no se puede conectar y usted puede recibir la siguiente exception …
     Network error IOException: Connection refused: connec

Ahora vamos a configurar estas dos opciones:

1. Habilitar TCP/IP
  1. Click Inicio > Todos los programas > Microsoft SQL Server 2005 > Herramientas de configuracion > SQL Server Configuration Manager.
  2. En el panel izquierdo de la ventana d e SQL Server Configuration Manager, expandir Configuracion de red de SQL Server 2005 y click en Protocolos de SQLEXPRESS.
  3. En el panel derecho de la ventana de SQL Server Configuration Manager,Click derecho en TCP/IP y click para habilit ar.
  4. O través click derecho en TCP/IP y c lick en propiedades.
  5. En la ventana de propiedades deTCP/IP, click en el panel direcciones ip, y expanda IPALL.
  6. Debajo de IPALL, borrar el campo de TCP Dynamic Ports y entonces ingrese un numero de puerto en el campo TCP Port. Usualmente, tiene el valor por defecto de 1433.
  7. En la ventana de propiedades TCP/IP, click OK.
  8. En el panel izquierdo de la ventana SQL Server Configuration Manager, click en Servicios de SQL Server 2005.
  9. En el panel derecho de la ventana de SQL Server Co nfiguration Manager,click derecho en SQL Server (SQLEXPRESS) y click en reinicar.

2. Habilitar la autenticación por conexión remota

Para resolver este problema. Uno es habilitar el modo de autenticación ambos SQL Server y Windows en el servidor y la otra es habilitar la conexión remota en el nave gador de SQL Server.
      • Chekear que usted tenga permitido el modo bo th SQL Server and Windows Authentication mode (Si usted no usa el modo Windows Authentication). Para la instancia del usuario ‘sa’.
1. Iniciar sesion usando SQL Server Management Studio Express al Servidor SQL y en modo Windows Authentication. Esto podría usar su cuenta de Windows para autenticarse con SQL Server.
2. En el objeto Explorador, click derecho en el nombre de instancia y seleccionar propiedades.


3. Seleccionar la página Security y cambiar la autenticación del servidor al modo SQL Server and Windows Authentication mode y presionar el boton Ok.
4. Click derecho otravés en el nombre de la instancia, seleccionar Restart para reiniciar el Servicio de SQL Server.

5. Esto es todo. Tienes habilitado el modoSQL Server and Windows authenticat ion, ahora usted puede iniciar sesion en SQL Server con su cuenta de Windows o su cuenta creada.

      • Chekear que usted tenga habilitado la conexión remota en Configuración de superficie de SQL Server
1. Abrir Configuración de superficie de SQL Server.


2. Seleccioar Configuracion de superficie para Servicios y Conexiones.


3. En el lado izquierdo, expandir su instancia de SQL Server -> Motor de base de datos -> Conexiones Remotas. En el lado derecho, seleccionar Conexiones locales y remotas -> Usar TCP/IP y canalizaciones con nombre.

4. En el lado izquierdo, seleccionar Explorador de SQL Server -> Servicio.
En el lado derecho, si el tipo de inicio esta Deshabilitado, usted necesita cambiarlo a Automatico. Clik en Aceptar.

5. Iniciar sesion usando SQL Server Management Studio Express al Servidor SQL y en modo Windows Authentication.

6. En el panel Object Explorer , expandir Security / nodo Logins.

7. Seleccionar el usuario "sa".

8. Click derecho en el usuario "sa"->propiedades e ingresar password para este usuario.


9. Luego seleccione la página Status y dele Click en la opcion enable de Login, Click en Ok

10. Click derecho otravés en el nombre de la instancia, seleccionar Restart para reiniciar el Servicio de SQL Server.

Probando lo hecho:

Usted ha finalizado la configuracion. Ahora intente iniciar sesion en su Servidor SQL de forma remota o en su computadora usando el modo SQL Server authentication.


Inicio de sesion a SQL Server con éxito.


sábado, 9 de febrero de 2008

Card PHP Cheat Sheet

Emezeta a realizado un resumen muy bueno de las funciones de php añadiendo pequeñas descripciones muy útiles al momento de buscar alguna información rápida.

Chuleta completa de PHP

sábado, 19 de enero de 2008

Curso de Ajax por el Dr. Diego de Ipiña

domingo, 13 de enero de 2008

Listas Genericas: Novedad en J2SE 5.0

sábado, 12 de enero de 2008

Zend Framework: Paginado (parte I)

Como sabran PHP esta evolucionando, gracias al aporte de todas las personas que comparten algo en común una pasion.

Desde que Ruby on Rails salio, PHP ha tenido que adaptarse al cambio, utilizar el patron modelo vista controlador, a partir de ese momento salieron a la luz muchos frameworks como prado, cakePHP entre otros, pero tambien se creo uno llamado zend framework que es el que utilizaremos para este ejemplo, que consiste en mostrar los resultados en un datagrid paginado, utilizando POO con PHP.

Software utilizado:



Comenzamos ... :$

Clases de utilidad
en primer lugar tengo que mostrar dos clases de persistencia que utilizo:

la clase DBManager.class.php
<?
/********************************************/
/* Clase DBManager */
/*Clase que administra las conexiones con */
/*la base de datos. */
/*Autor: Hugo Flores Joseph 2006 */
/*Copyright (c) */
/********************************************/
require_once('Recordset.class.php');

class DBManager{

private $host='localhost';
private $db ='agenda';
private $user='';
private $pass='';
private $connectionID;// Retorna un enlace identificador de la conexion hecha con la base de datos
private $queryID = -1;// Esta variable guarda elúltimo resultado creado por link identifier de una consultra (almacena un entero<true=1,false=0>)
private $tempResultObj = '';// Almacena el resultado del Objeto Recientemente creado via el método execute()
private $error="";


//----------------Métodos Públicos--------------------//

public function DBManager($user='',$pass='')
{
if(!empty($user))$this->user=$user;
if(!empty($pass))$this->pass=$pass;

try{
$this->connectionID=@mysqli_connect($this->host,$this->user,$this->pass,$this->db);
if(!$this->connectionID) throw new Exception(mysqli_connect_error());
}
catch(Exception $e)
{
echo "A ocurrido un error: ".$e->getMessage();
exit();//termina la ejecucion del script
}
}

//funcion ADHOC utilizada con SELECT
public function executeQuery($sql = "")
{
$this->queryID = mysqli_query($this->connectionID,$sql);
$this->tempResultObj = new Recordset($this->queryID);//Inicializa un objeto sin considerar si la consulta retorna algun resultado o no.
return $this->tempResultObj;
}
//funcion ADHOC utilizada con INSERT, UPDATE, DELETE
public function executeUpdate($sql = "")//devuelve falso si la consulta tuvo exito
{
$resp=false;
$this->queryID = @mysqli_query($this->connectionID,$sql); //Inicializa un objeto sin considerar si la consulta retorna algun resultado o no.
if($this->queryID) $resp=true;
return $resp;
}
public function getConnection() { return $this->connectionID;}
public function closeConnection(){ mysqli_close($this->connectionID);}
}
?>


La segunda clase que utilizaremos es Recordset.class.php, esta clase tiene un comportamiento similar a java.sql.ResultSet de Java:
<?
/********************************************/
/* Clase Recordset */
/* clase que me permite manejar un conjunto */
/* de registros de una base de datos */
/* MySQL. */
/* Autor: Hugo Flores Joseph 2006 */
/* Copyright (c) */
/********************************************/

class Recordset{
//------Variables Públicas---------//
public $fields;
public $BOF = null;// indica que la posición actual del registro esta antes del primer registrp en un Objeto Recordset.
public $EOF = null;// indica que la posición actual del registro esta después del último registro en un Objeto Recordset.

//------Variables Privadas---------//
private $_numOfRows = -1; // No Cambie este valor! SOLO LECTURA!
private $_numOfFields = -1; // No Cambie este valor! SOLO LECTURA!
private $_tempResult = '';// Almacena un valor que fue retornado desde una función específica de la Base de Datos
private $_queryID = -1;// Esta variable guarda el resultado de un link identifier
private $_currentRow = -1;// Esta variable guarda la actual fila en un Recordset.

//------Métodos--------------------//
// Devuelve: query id exitoso o falso si
// la función Constructor ha fallado
public function Recordset($queryID)
{
$this->_queryID = $queryID;
if ($queryID) {
$this->_numOfRows = @mysqli_num_rows($this->_queryID);
$this->_numOfFields = @mysqli_num_fields($this->_queryID);//devuelve el número de campos de la consulta o result set
}
else {
$this->_numOfRows = 0;
$this->_numOfFields = 0;
}
// Si el resultado contiene filas
if ($this->_numOfRows > 0 && $this->_currentRow == -1) {
$this->_currentRow = 0;
$this->fields = mysqli_fetch_array($this->_queryID);//captura la fila en un array mssql_fetch_aaray(Devuelve: Un array que corresponde a la fila capturada, o FALSE si no hay más filas)
$this->EOF = false;
$this->BOF = false;
}
return $this->_queryID;
}//fin de método Recordset

// Devuelve: True si hay todavía filas disponibles, o False
// si no hay mas filas. Mueve a la proxima fila en un
// Objeto Recordset Especifico y hace que el registro de la fila actual
// y la correspondiente informaciónde la fila se recupere
// en la colección de los campos. Note: Al contrario del método moveRow(),
// cuando _currentRow esta getNumOfRows() - 1, EOF podria inmediatamente ser
// True. Si el número de fila no es proporcionado, la funcion podria posicionarse
//automáticamente en la primera fila.
public function nextRow()
{
if ($this->getNumOfRows() > 0)
{
$this->fields = array();
$this->_currentRow++;
$this->fields = @mysqli_fetch_array($this->_queryID);
// Esto esta no trabajando. True todo el tiempo
if ($this->fields)
{
$this->_checkAndChangeEOF($this->_currentRow - 1);
return true;
}
}
$this->EOF = true;
return false;
}//fin de método nextRow()

// Devuelve: true si es exitoso, false si ha fallado moveRow()
// moueve el puntero interno de una fila de el Objeto Recordset
// hacia un puntero de una fila especifico y la correspondiente
// información de la fila que podria recuperarse de la colección de
// campos. Si el número de fila no es proporcionado, la funcion podria posicionarse
// automáticamente en la primera fila.
public function moveRow($rowNumber = 0)
{
if ($rowNumber == 0) {
return $this->firstRow();
}
else if ($rowNumber == ($this->getNumOfRows() - 1)) {
return $this->lastRow();
}
if ($this->getNumOfRows() > 0 && $rowNumber < $this->getNumOfRows()) {
$this->fields = null;
$this->_currentRow = $rowNumber;
if(@mysqli_data_seek($this->_queryID, $this->_currentRow)) {//mueve el puntero interno de las filas Devuelve: TRUE si se ejecuta con éxito, FALSE si falla
$this->fields = @mysqli_fetch_array($this->_queryID);
/* This is not working. True all the time */
if ($this->fields) {
// No necesita llamar a _checkAndChangeEOF() por que
// la posibilidad de mover hacia la última fila ha
// sido manejada por el código de arriba
$this->EOF = false;
return true;
}
}
}
$this->EOF = true;
return false;
}//fin de moveRow()

// Devuelve: true en caso de exito, false en caso de fallo de lastRow() moueve
// el puntero interno de la fila de un Objeto Recordset hacia la última fila
// y recupera la correspondiente información de la fila
// de la collecion de campos.
public function lastRow()
{
if ($this->getNumOfRows() > 0) {
$this->fields = array();
$num_of_rows = $this->getNumOfRows();
$this->_tempResult = @mysqli_data_seek($this->_queryID, --$num_of_rows);//Devuelve: TRUE si se ejecuta con éxito, FALSE si falla y es --$num_of_rows por que en sql
if ($this->_tempResult) { //existe un ultimo registro en blanco entonces tengo que posicionarme en el
/* $num_of_rows decrementado anterioemente */ //penultimo registro.
$this->_currentRow = $num_of_rows;
$this->fields = @mysqli_fetch_array($this->_queryID);
/* Esto no esta trabajando. Verdadero todo el tiempo */
if ($this->fields) {
/* Caso Especial para hacer EOF=fallse. */
$this->EOF = false;
return true;
}
}
}
$this->EOF = true;
return false;
}//fin de método lastRow()

// Devuelve: true en caso de éxito, false en caso de fallo, firstRow() mueve
// el puntero interno de la fila de un Objeto Recordset hacia la primera fila
// y recupera la correspondiente información de la fila
// de la collecion de campos.

public function firstRow()
{
if ($this->getNumOfRows() > 0) {
$this->fields = array();
$this->_currentRow = 0;
if (@mysqli_data_seek($this->_queryID, $this->_currentRow)) {
$this->fields = @mysqli_fetch_array($this->_queryID);
$this->EOF = false;
/* Esto no esta trabajando. Verdadero todo el tiempo */
if ($this->fields) {
return true;
}
}
}
$this->EOF = true;
return false;
}


// Retorna: El número de filas de un resultado.
public function getNumOfRows(){return $this->_numOfRows;}

/* Chequea y Cambia el Estado de EOF. */
public function _checkAndChangeEOF($currentRow)
{
if ($currentRow >= ($this->_numOfRows - 1))
{
$this->EOF = true;
}else{
$this->EOF = false;
}
}

// close() solo necesita ser llamado si esta usando mucha memoria
// al correr su script. libera la memoria.

public function close()
{
$this->_tempResult = @mysqli_free_result($this->_queryID);
return $this->_tempResult;
}
}//fin de la clase
?>
Configurando nuestro proyecto
Una vez que tenemos estas dos clases procederemos a organizar nuestro proyecto siguiendo la estructura de directorio recomendada por el framework dentro del directorio htdocs de Apache, creamos una carpeta llamada zfpaging y los subdirectorios lo siguientes:


application/
controllers/
IndexController.php
models/
views/
scripts/
index/
index.phtml
helpers/
filters/
html/
.htaccess
index.php


La estructura que se muestra es la configuracion por defecto de un proyecto con zend framework, pero lo vamos a adaptar a lo que nostros utilizaremos:

application/
controllers/
IndexController.php
models/
views/
scripts/
index/
index.phtml
helpers/
filters/
.htaccess
library/
paging/
sql/
zend/
.htaccess
public/
images/
scripts/
styles/
.htaccess
.htaccess
index.php