jueves, 10 de febrero de 2011

Porque debería usar PHP’s PDO Para acceder a Bases de Datos? Parte 2

Insertar y actualización
Inserción de nuevos datos o actualizar los datos existentes es una de las operaciones de base de datos más comunes. Uso de DOP, esto es normalmente un proceso de dos pasos. Todo lo descrito en esta sección se aplica por igual tanto INSERT como para UPDATE.

Aquí un ejemplo del tipo más básico de inserción:

# STH means "Statement Handle"
$STH = $DBH->prepare("INSERT INTO person ( first_name ) values ( 'Cathy' )");
$STH->execute();

También se puede realizar la misma operación utilizando el método exec(). En la mayoría de los casos, usted va a utilizar el método más largo para lograr tomar ventaja de declaraciones preparadas. Incluso si sólo va a utilizarla una vez, ya que las declaraciones preparadas le ayudarán a protegerse de los ataques de inyección SQL.

Sentencias preparadas
El uso de declaraciones preparadas le ayudará a protegerse de la inyección de SQL.


Una declaración preparada es una instrucción SQL precompilada que se pueden ejecutar varias veces mediante el envío sólo de datos al servidor. Tiene la ventaja adicional de establecer de forma automática los datos utilizados en los marcadores de posición asegurándonos así de un ataque de inyección SQL.
Utilice una declaración preparada mediante la inclusión de marcadores de posición (parámetros) en su instrucción SQL. Veamos 3 ejemplos: uno sin marcadores de posición, uno con marcadores de posición sin nombre, y uno con marcadores de posición con nombre.


// sin marcadores de posición
$STH = $DBH->("INSERT INTO person (name, addr, city) values ($name, $addr, $city)");

# usando marcadores de posición sin nombre
$STH = $DBH->("INSERT INTO person (name, addr, city) values (?, ?, ?) ");

# usando marcadores de posición con nombre
$STH = $DBH->("INSERT INTO person (name, addr, city) value (:name, :addr, :city)");


Es recomendable evitar el primer método, que se utiliza aquí para la comparación. La opción de usar marcadores con nombre o sin nombre afectará la forma de configurar los datos en las instrucciones SQL.

Marcadores de posición sin nombre


$STH->bindParam(1, $name);
$STH->bindParam(2, $addr);
$STH->bindParam(3, $city);

$name = "Daniel"
$addr = "1 Wicked Way";
$city = "Arlington Heights";
$STH->execute();

$name = "Steve"
$addr = "5 Circle Drive";
$city = "Schaumburg";
$STH->execute();



Contamos con dos pasos para ejecutar nuestras sentencias SQL. En primer lugar, asignamos variables diferentes a los marcadores de posición (líneas 2-4). Luego, asignamos valores a los marcadores de posición y por ultimo ejecutamos nuestra sentencia SQL. Para ejecutar otra sentencia SQL solo será necesario cambiar los valores de las variables y ejecutar nuevamente la sentencia SQL.

¿Esto parece un poco difícil de manejar para las sentencias con una gran cantidad de parámetros? Eso es cierto. Sin embargo, si los datos se almacenan en una matriz, hay una opción más corta:


$data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff');

$STH = $DBH->("INSERT INTO person (name, addr, city) values (?, ?, ?);
$STH->execute($data);



Waao, Que fácil!
Los datos de la matriz se aplican a los marcadores de posición en orden secuencial. $data[0] será asignado al primer marcador de posición, $data[1],en el segundo, etc Sin embargo, si los índices de matriz no están en orden, esto no funcionará muy bien que digamos, y se tendrá que volver a indexar la matriz.

Marcadores de posición con nombre
Probablemente se podría adivinar la sintaxis, pero aquí dejo un ejemplo:


$STH->bindParam(':name', $name);


Aquí también se puede utilizar una matriz (array), pero en este caso trabaja con las matrices asociativas. Ejemplo:


$data = array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' );

# the shortcut!
$STH = $DBH->("INSERT INTO person (name, addr, city) value (:name, :addr, :city)");
$STH->execute($data);


No es necesario que las claves de la matriz comiencen con dos puntos, pero todo lo demás es necesario para lograr que coincidan los valores en los marcadores de posición con nombre. Si usted tiene una matriz de matrices se puede iterar sobre cada una de ellas, y simplemente ejecute su sentencia SQL con cada conjunto de datos.

Otra característica interesante de los marcadores de posición con nombre es la posibilidad de insertar objetos directamente en la base de datos, suponiendo que las propiedades del objeto coinciden con los campos con nombre. Veamos un ejemplo con un objeto y cómo añadirlo:


class person {
public $name;
public $addr;
public $city;

function __construct($n,$a,$c) {
$this->name = $n;
$this->addr = $a;
$this->city = $c;
}
# ...
}

$cathy = new person('Cathy','9 Dark and Twisty','Cardiff');

$STH = $DBH->("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
$STH->execute((array)$cathy);




Se convierte el objeto en una matriz y se ejecuta la sentencia SQL, las propiedades son tratadas como claves de matriz.

Seleccionando datos

Los datos se obtienen a través del metodo -> fetch (), el cual es un método de nuestro identificador de instrucción. Antes de llamar a fecth(), lo mejor es decirle PDO cómo quieres obtener los datos. Para lo cual se cuenta con las siguientes opciones:
PDO:: FETCH_ASSOC: devuelve una matriz indexada por nombre de columna
PDO:: FETCH_BOTH (por defecto): devuelve una matriz indexada por nombre y número de columna
PDO:: FETCH_BOUND: Asigna los valores de las columnas a las variables definidas con el metodo ->bindColumn()
PDO:: FETCH_CLASS: Asigna los valores de las columnas a las propiedades de la clase. Se crearan las propiedades si no existen
PDO:: FETCH_INTO: Actualiza una instancia existente de la clase especificada.
PDO:: FETCH_LAZY : Combina PDO:: FETCH_BOTH/DOP:: FETCH_OBJ, creando los objetos y las variables para su uso.
PDO:: FETCH_NUM: devuelve una matriz indexada por número de columna.
PDO:: FETCH_OBJ: devuelve un objeto anónimo con nombres de propiedades que corresponden a los nombres de columna.

En realidad, hay tres que cubren la mayoría de las situaciones: FETCH_ASSOC, FETCH_CLASS y FETCH_OBJ. La sintaxis que se utiliza con el fin de establecer el método fecth() es la siguiente:


$STH->setFetchMode(PDO::FETCH_ASSOC);


FETCH_ASSOC

Este crea una matriz asociativa, indexada por nombre de columna. Esto debería ser muy familiar para cualquiera que haya usado las extensiones mysql/mysqli. Veamos un ejemplo de selección de datos con este método:


# creamos nuestra sentencia SQL
$STH = $DBH->query('SELECT name, addr, city from person);

# configuramos el modo deseado
$STH->setFetchMode(PDO::FETCH_ASSOC);

while($row = $STH->fetch()) {
echo $row['name'] . "\n";
echo $row['addr'] . "\n";
echo $row['city'] . "\n";
}


El bucle while se ejecuta hasta terminar de escribir en pantalla el resultado obtenido.

FETCH_OBJ

Este crea un objeto para cada fila de datos captados. Ejemplo:


# creamos nuestra sentencia SQL
$STH = $DBH->query('SELECT name, addr, city from person);

# configuramos el modo deseado
$STH->setFetchMode(PDO::FETCH_OBJ);

# mostramos el resultado
while($row = $STH->fetch()) {
echo $row->name . "\n";
echo $row->addr . "\n";
echo $row->city . "\n";
}


FETCH_CLASS
Las propiedades del objeto se establecen antes que el constructor sea llamado. Esto es importante.


Este método le permite recuperar los datos directamente en una clase especificada. Cuando se utiliza FETCH_CLASS, las propiedades de su objeto se establecen antes de llamar al constructor. Las propiedades que no existan como según las columnas obtenidas se crearan automáticamente.
Esto significa que si sus datos necesitan cualquier transformación después de salir de la base de datos, se pueden hacer automáticamente por su objeto, ya que cada objeto es creado.
Ejemplo, imagine una situación en la que la dirección tiene que ser parcialmente protegida por cada registro. Podemos hacer esto operando con la propiedad en el constructor. veamos:


class secret_person {
public $name;
public $addr;
public $city;
public $other_data;

function __construct($other = '') {
$this->address = preg_replace('/[a-z]/', 'x', $this->address);
$this->other_data = $other;
}
}


Como los datos se traen en esta clase, la dirección tiene caracteres entre a-z en minúscula y la sustituiremos por la letra x. Ahora, al momento de usar la clase todas las transformaciones curren de forma transparente:


$STH = $DBH->query('SELECT name, addr, city from person);
$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person');

while($obj = $STH->fetch()) {
echo $obj->addr;
}


Si la dirección es “5 Bronds”, se obtendrá “5 Bxxxxx”. Por supuesto, puede haber situaciones en las que desea que el constructor se llame antes de asignar los datos. PDO ofrece una solución ante esto también.


$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'secret_person');


Ahora, cuando se repita el ejemplo anterior con este modo establecido (PDO:: FETCH_PROPS_LATE) La dirección no se oculta, ya que el constructor se llama y las propiedades ya fueron asignadas.
Por último, si usted necesita pasar argumentos al constructor durante la obtención de datos en objetos con PDO, use el siguiente modo:


$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person', array('stuff'));


Si usted necesita para pasar datos de forma dinámica al constructor para cada objeto, puede establecer el modo al momento de ejecutar fecth():


$i = 0;
while($rowObj = $STH->fetch(PDO::FETCH_CLASS, 'secret_person', array($i))) {
$i++
}



Conclusión
Espero que estos dos artículos ayuden a muchos programadores a cambiarse de las extensiones mysql y mysqli.

lunes, 31 de enero de 2011

Porque debería usar PHP’s PDO Para acceder a Bases de Datos? Parte 1

Muchos programadores aprendieron como obtener acceso a bases de datos mysql usando las extensiones mysql o mysqli.
A partir de PHP 5.1, se encuentra disponible una mejor opción. PDO (PHP Data Objects) provee métodos para preparar consulta SQL
Y trabajar con objetos que le harán mucho más productivo!

Introducción PDO
“PDO – PHP Data Objects – es una capa de acceso estandarizada que proporciona un método uniforme de acceso a múltiples bases de datos”.
No toma en cuenta para la sintaxis de base de datos específica, pero puede permitir migrar fácilmente de entre motores bases de datos y plataformas sin muchos dolores de cabeza, cambiando la cadena de conexión en la mayoría de los casos.
Este post está dirigido a personas que actualmente usan las extesiones mysql y mysqli para obtener acceso a bases de datos.

Motores de Bases de datos soportados
La extensión puede soportar cualquier base de datos para que exista escrito un driver PDO. Actualmente los controladores de bases de datos disponibles son las siguientes:

• PDO_DBLIB ( FreeTDS/Microsoft SQL Server/Sybase )
• PDO_FIREBIRD ( Firebird/Interbase 6 )
• PDO_IBM ( IBM DB2 )
• PDO_INFORMIX ( IBM Informix Dynamic Server )
• PDO_MYSQL ( MySQL 3.x/4.x/5.x )
• PDO_OCI ( Oracle Call Interface )
• PDO_ODBC ( ODBC v3 (IBM DB2, unixODBC ywin32 ODBC) )
• PDO_PGSQL ( PostgreSQL )
• PDO_SQLITE ( SQLite 3 ySQLite 2 )
• PDO_4D ( 4D )
Todos estos controladores no están necesariamente disponibles en su sistema, una forma rápida de saber con que controladores se cuenta en el sistema:

print_r(PDO::getAvailableDrivers());

Establecer Conexión
Diferentes bases de datos pueden tener diferentes métodos de conexión. A continuación, muestro el método para conectarse a algunos de los motores de bases de datos más populares. Observe que los tres primeros son idénticos a excepción de la conexión SQLite el cual cuenta con una sintaxis propia.

try {
// MS SQL Server ySybase con PDO_DBLIB
$DBH = new PDO("mssql:host=$host;dbname=$dbname, $user, $pass");
$DBH = new PDO("sybase:host=$host;dbname=$dbname, $user, $pass");

// MySQL con PDO_MYSQL
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);

// SQLite
$DBH = new PDO("sqlite:my/database/path/database.db");
}
catch(PDOException $e) {
echo $e->getMessage();
}

Por favor, tome nota del bloque try/catch, siempre debe realizar sus operaciones PDO en un try/catch, y utilizar el mecanismo de excepción pertinente, esto lo veremos en breve. Normalmente, usted sólo va a hacer una sola conexión, $DBH representa nuestra conexión a la base de datos que especifiquemos.
Usted puede cerrar cualquier conexión estableciendo la instancia del objeto en null.

//SQLite
$DBH = null;

Puede obtener más información sobre las opciones específicas de base de datos y/o cadenas de conexión para otras bases de datos en PHP.net .

PDO y las Excepciones
PDO puede utilizar excepciones para controlar los errores. Puede forzar PDO en uno de los tres modos de error al establecer el atributo error mode en la conexión de su base de datos. Ésta es la sintaxis:

$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

No importa el valor que se establezca en el error mode, un error de conexión siempre produce una excepción y la creación de una conexión siempre debe estar contenida en un bloque try/catch.

PDO:: ERRMODE_SILENT
Este es el modo de error por defecto. Si lo deja en este modo, se debe comprobar si hay errores. Los otros dos métodos son más ideales para la programación de SECO.

PDO:: ERRMODE_WARNING
Este modo emitirá un nivel de alerta de PHP, y permite a la programa continuar con su ejecución. Es útil en procesos de depuración.

PDO:: ERRMODE_EXCEPTION
Este es el modo sugerido en la mayoría de las situaciones. Se dispara una excepción, lo que le permite controlar los errores con gracia y ocultar los datos que puedan ayudar a alguien a realizar operaciones mal intencionadas en el sistema. Un ejemplo de tomar ventaja de las excepciones:

// Conexion
try {
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

//Error incrustado DELECT = DELETE
$DBH->prepare('DELECT name FROM employee);
}
catch(PDOException $e) {
echo "Boom!!!!.";
file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
}

Hay un error intencional en la instrucción de selección, lo que provocará una excepción. La excepción envía los detalles del error a un archivo de registro, y muestra un mensaje amistoso (o no muy claro) para el usuario.

miércoles, 12 de enero de 2011

Crear un componente (control) Font ComboBox personalizado

En este caso publico el video del post anterior para facilitar su compresión.

miércoles, 29 de diciembre de 2010

Crear un componente (control) Font ComboBox personalizado

Para este post me apoyo en la documentación oficial de CSharp correspondiente a la creación de componentes y controles personalizados.

Lo primero que haremos sera agregar una nueva clase a nuestro proyecto en CSharp con el nombre FontComboBox y heredamos de la clase ComboBox lo siguiente por hacer es rellenar el control con el listado de fuentes del sistema.

Código

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.ComponentModel;

namespace CustomControl
{
internal class FontComboBox : ComboBox
{

Pen p = new Pen(Color.Black);
StringFormat sf = new StringFormat();
Font f = new Font("Arial", 8);

internal FontComboBox()
{
this.DrawMode = DrawMode.OwnerDrawFixed;
sf.Trimming = StringTrimming.None;
sf.FormatFlags = StringFormatFlags.NoWrap;
if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
ListFonts();
this.DropDownHeight = 300;
this.Font = new Font(this.Font.Name, 12);
this.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
this.AutoCompleteSource = AutoCompleteSource.ListItems;
this.MaxDropDownItems = 20;
}

protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e);

try
{
FontFamily ff = new FontFamily(this.Items[e.Index].ToString());

if (ff.IsStyleAvailable(FontStyle.Regular) == true)
{
f = new Font(this.Items[e.Index].ToString(), this.Font.Size, FontStyle.Regular);
}
else if (ff.IsStyleAvailable(FontStyle.Italic) == true)
{
f = new Font(this.Items[e.Index].ToString(), this.Font.Size, FontStyle.Italic);
}
else if (ff.IsStyleAvailable(FontStyle.Bold) == true)
{
f = new Font(this.Items[e.Index].ToString(), this.Font.Size, FontStyle.Bold);
}
else
{
f = new Font("Microsoft Sans Serif", this.Font.Size, FontStyle.Regular);
}
}
catch (Exception)
{
f = new Font(this.Items[e.Index].ToString(), this.Font.Size, FontStyle.Bold);
}
p = new Pen(this.ForeColor);

e.DrawBackground();

e.Graphics.DrawString(this.Items[e.Index].ToString(), f, p.Brush, e.Bounds);

if (e.State == DrawItemState.Focus)
e.DrawFocusRectangle();

//Liberamos la memoria
p.Dispose();
f.Dispose();
}

private void ListFonts()
{
this.Items.Clear();
System.Drawing.Text.InstalledFontCollection ifc = new System.Drawing.Text.InstalledFontCollection();
this.BeginUpdate();
foreach (FontFamily ff in ifc.Families)
{
this.Items.Add(ff.Name);
}

this.EndUpdate();
}

}
}



He agregado el código y un par de personalizaciones visible como auto-completado.

jueves, 16 de diciembre de 2010

QT DevDay disponible

el día de hoy me dado una pasada por el portal de QT, donde me encuentro con la novedad de que y a se encuentran disponible en video la primera tanda (parte) de videos elaborados por el equipo de aprendizaje de qt en la presentaciones DevDay de este año, ademas están disponible para descarga las diapositivas utilizadas durante las exposiciones.

aqui les dejo el enlace a los detalles de esta recopilación, lo cual es algo que me parece excelente.


martes, 14 de diciembre de 2010

Convertir .p12 a .pem

ya algunos compañeros y uno que otro forero me había preguntado antes ¿Como convierto un fichero .p12 a .pem? creo esto ya seria un post para mi blog.

Un fichero .P12 contiene toda la información que compone un certiricado digital x.509 basado en PKCS #12 el cual puede ser utilizado para firmar documentos digitales, mensajes soap entre otros.

es bueno utilizar openssl para trabajar con ficheros .p12 (certificados en general), en el link podras encontrar la documentación correspondiente a openssl y su forma de uso.

luego de descargar e instalar openssl podemos convertir nuestro .P12 a .PEM asi:

openssl pkcs12 -clcerts -nokeys -in certificado.p12 -out nuevoCertificado.pem
openssl pkcs12 -nocerts -in certificado.p12 -out nuevaKey.pem

como puedes es algo claro lo que se hace verdad? ahora el proceso invertido seria asi:

openssl pkcs12 -export -out certificado.p12 -inkey ./nuevaKey.pem -in ./nuevoCertificado.pem

Tambien podemos utilizar algunas herramientas para trabajar con archivos de certificados como: QuickPar, PGP Desktop, OpenPGP, XCA.

miércoles, 6 de octubre de 2010

Reporte Global de Competitividad

El Reporte Global de Competitividad (RGC) es una publicación anual del Programa de Competitividad Global del FEM que presenta una evaluación comparativa de las debilidades y fortalezas de las 104 economías del mundo para el año 2004 desde el punto de vista de su competitividad internacional. El RGC basa su análisis es dos enfoques diferentes pero complementarios en el análisis de la competitividad económica.

El primero, liderado por Jeffrey D. Sachs del Centro de Desarrollo Internacional de la Universidad de Harvard se basa en el concepto de competitividad global como «el conjunto de instituciones y políticas económicas que sirven de apoyo a la existencia de altas tasas de crecimiento económico en el mediano plazo». Las ediciones del RGC previas al año 2000 publicaban un índice general basado en este enfoque, conocido simplemente como el índice de competitividad. Desde el año 2000, este indicador fue renombrado como el Índice de Crecimiento de la Competitividad (ICC). Con base en fundamentos macroeconómicos teóricos y empíricos, el FEM calcula el ICC como la mejor estimación de las perspectivas de crecimiento durante los próximos cinco años para las 102 economías analizadas.

El segundo enfoque que se sigue en el RGC corresponde al liderado por Michael E. Porter del Instituto de Estrategia y Competitividad de la Escuela de Administración de la Universidad de Harvard, el cual es capturado por el Índice de Competitividad Actual (ICA), presentado en la edición 2000 pero que para el año 2003 es nombrado como Índice de Competitividad Empresarial (ICE). El ICE hace uso de indicadores microeconómicos para la medición del «conjunto de instituciones, estructuras de mercado y políticas económicas que sirven de base para el logro de altos niveles de prosperidad». Lo que se refiere principalmente a la efectiva utilización que hace la economía de su acervo actual de recursos. Así, este índice evalúa el potencial productivo actual de las mismas 102 economías analizadas. En conjunto, el ICC y el ICE presentan dos enfoques distintos pero complementarios con los que se exploran las fuentes de la competitividad nacional.

Tanto el ICC como el ICE combinan datos cuantitativos con datos cualitativos obtenidos de la aplicación de una encuesta de opinión diseñada para evaluar aspectos relacionados con la competitividad de un amplio grupo de países. De gran importancia para el cálculo de estos indicadores es la encuesta de opinión empresarial adelantada anualmente por el Foro Económico Mundial, la cual permite derivar datos sobre una buena cantidad de aspectos de la economía de un país para los que no existen datos cuantitativos, tales como la eficiencia de las instituciones de gobierno, la sofisticación de las redes de abastecimiento local, o la naturaleza de las prácticas competitivas.

Como gran novedad para este año, el reporte incluye un nuevo índice de competitividad: El Índice Global de Competitividad (IGC). Este se diseñó con el objeto de unificar los dos índices actualmente utilizados, y se prevé que sean remplazados eventualmente en el RGC.

La publicación del RGC tiene lugar cada año en el mes de octubre.

Con base en los resultados del Reporte Global de Competitividad se elabora anualmente para Colombia lo que se conoce como Matriz de Competitividad, (Archivo.zip)) (Para ver este archivo, debe descargarlo, primero, al disco duro).

Esta matriz fue desarrollada como un instrumento de recopilación y análisis de las variables que componen los factores de competitividad del FEM (tomando como el RGC 1999, año de lanzamiento de la Política Nacional de Productividad y Competitividad) con el objetivo de identificar sistemáticamente campos prioritarios de acción conjunta entre los sectores público y privado en el campo de la competitividad. De esta forma, la matriz se ha constituido en el instrumento que permite priorizar las acciones a desarrollar por las Redes Especializadas de la Red Colombia Compite

Usted puede consultar el documento de analisis elaborado por el Ministerio de Comercio Exterior, sobre la posición de Colombia en este estudio: