Mostrando entradas con la etiqueta PHP. Mostrar todas las entradas
Mostrando entradas con la etiqueta PHP. Mostrar todas las entradas

jueves, 15 de diciembre de 2016

Dilema de las clases estáticas en PHP

En mi búsqueda interminable por conseguir estratégias para abordar problemas cotidianos en la programación, hoy coloco esta idea como propuesta para resolver la ambigüedad de las clases estáticas en PHP.

Un poco de teoría para empezar.

¿Que es una clase estática?

Una clase estática, es una clase declarada como estática, que puede ser accedida o invocada sin la necesidad de tener que instanciar un objeto de la clase.

Y ¿Qué significa esto?. Pues bien, de acuerdo a la teoría si queremos hacer una instancia de la clase que queremos definir como estática pues no nos debe permitir hacer esto.


$miClase = new MiClase (); // Esto debe dar un error
Pero PHP no nos genera error al instanciar esta clase.

Por otro lado podríamos omitir el constructor ( cosa que veo mucho por internet en las definiciones de clases y que me parece una mala práctica, creo que toda clase debe tener su constructor y tener además la inicialización de variables en su interior ), pero PHP por omisión acepta la instanciación de la clase pues asume un constructor en blanco o vacío por omisión ante la ausencia explicita de este. Cosa que no resuelve nuestro dilema.

Otra opción muy viable, que funciona y es efectiva, sería colocar el o los modificadores private o protected al constructor, es decir,


private(protected) function __constructor () {

  // nuestro código de inicialización
}
Pero para que colocar código de inicialización si de igual manera no se puede instanciar y no se ejecutará esa sección de código. Pues bueno es solo un ejemplo capcioso para que se confundan jajajaja. Lo cierto es que si colocamos el constructor en private o protected al intentar instanciarlo PHP nos devolverá un error pues el constructor no tiene la visibilidad requerida para ser ejecutado. Pero adicional a esto, ¡que sentido tiene colocar un constructor en private o protected que no se puede usar!. Mejor obviamos esas líneas de código innecesarias, nuestro código queda mucho más limpio, fácil de leer y menos oportunidad para confundirnos.

Ahora bien, mi propuesta para resolver la ambigüedad de las clases estáticas en PHP es la de definir la clase como "ABSTRACTA" de la siguiente manera:


abstract class MiClase {

  static public $atributo_1 = EL_VALOR_QUE_SE_REQUIERA;

  static public function miFuncion ( mi_lista_de_parametros ) {

    // nuestro código
  }
}
Así, al intentar instanciarla como en el primer cuadro de ejemplo, nos devolverá un error, cosa que debe suceder pues en teoría es una clase "estática" y como dije anteriormente, nuestro código queda mucho más limpio, fácil de leer y menos oportunidad para confundirnos.

sábado, 21 de junio de 2014

Eclipse a tono para trabajar con PHP

Buenas a todos los mis amigos e internautas que me leen y revisan el blog, hoy después de tanto tiempo he vuelto a desempolvar este espacio que me ayuda a desestresarme de mi día a día.


Hoy después de mucho tiempo he vuelto a linux y como es habitual hay que comenzar a configurar muchas cosas, pero por razones de trabajo no tengo mucho tiempo para sentarme a configurar todo como quiero, así que empecé por configurar Eclipse, que es mi herramienta de trabajo para casi todo lo que tiene que ver con programación.


Aquí les dejo una pequeña pero muy completa configuración que siempre realizo en Eclipse para hacer que programar en PHP sea un juego de niños :p.


Expresiones Regulares

Para hacer fácil la tarea de generar expresiones regulares



PDT - Extensions

Posee un generador de clases e interfaces muy al estilo de la perspectiva Java e integrado a nuestro proyecto y librerías PHP. Además nos permite definir nuestras propias reglas para la sintaxis, estándares y convenciones a los cuales estamos acostumbrados a trabajar, sobre todo en mi caso que trabajo con una configuración de estándares bastante simple pero a la vez compleja toda vez que utilizo algunos estándares de C/C++, Java, PHP y algunos propios, todo eso junto :).



PTI - PHP Tool Integration 1.6.0

Nos ofrece una seria de herramientas como PHP_CodeSniffer, PHPUnit, PHP Depend, PHP Copy/Paste Detector, para una mejor estandarización de nuestro código, además de un complemento a las PDT-Extensions.



Jasper Studio

Para generar nuestros reportes, si bien no es fácil trabajar Java y PHP juntos, pero si se puede, hay algunas herramientas que nos permiten realizar esta tarea aunque con algunos dolores de cabeza jejeje.



Bueno, esto es todo por ahora, pero viene mucho más de PHP, C/C++, Qt, Java, GNU/Linux(Debian) y otras Hierbas ;).

domingo, 3 de junio de 2012

Manejo de transparencias en imagenes PNG y BLOB Mysql

Hace un tiempo tuve un inconveniente con los tipos de datos blob para mostrar imagenes de tipo png con transparencias. Si bien muchas personas en su  momento me criticaron por querer guardar imagenes en una base de datos, yo seguí empeñado en mi idea, y gracias a DIOS que seguí firme en mi convicción.

Si bien aparentemente hay que hacer más procesos por el hecho subir la imagen al servidor y convertir la imagen a tipo binario para poder guardarla  en la base de datos, me he dado cuenta que el rendimiento de mis páginas ha sido mejor, pues al mostrarlas no tengo que reconvertirlas, pues las muestro tal cual son, un dato binario, que por otro lado pesan mucho menos que una imagen de archivo físico.

Voy a mostrar el proceso para archivos de imagen de tipo png pero el procedimiento es análogo para imagenes de tipo jpeg y gif. He de acotar que todo está desarrollado bajo POO y aconsejo tener un poco de conocimiento sobre el tema para una mejor comprensión del ejemplo, pero igual puede ser utilizado en forma de script.

Pues bien, sin más ni menos, aquí lo que se necesita para hacer la conversión para guardar la imagen en base de datos y luego mostrarla.

Para convertir la imagen a blob necesitaremos la siguiente función:



/**
     * Convierte un archivo png en formato binario.
     *
     * @param string $archivo Url de la imagen.
     * @return binary Objeto de tipo blob.
     */
    public static function pngABlob ( $archivo ) {

        $imagenCreada = imagecreatefrompng ( $archivo );

        if ( imagealphablending ( $imagenCreada, true ) ) {//SI SE ESTABLECE EL CANAL ALPHA

            imagesavealpha ( $imagenCreada, true );
        }
        ob_start ();
        imagepng ( $imagenCreada );
        $imagen = ob_get_contents ();
        ob_end_clean ();
        return base64_encode ( $imagen );
    }


Explicando un poco, la función imagecreatefrompng crea una nueva imagen a partir de un archivo o de una URL.

La función imagealphablending establece el modo de mezcla para la imagen, debe llevar el segundo parámetro en "TRUE" para establecer el canal alpha de la imagen obtenida de la función anterior.

La función imagesavealpha permite guardar la información completa del canal alpha que se há creado con la función anterior, también debe llevar el segundo parámetro en "TRUE".

La función imagepng procesa la imagen obtenida.

Con la función ob_get_contents capturamos el contenido del búfer de salida del procesamiento de la función anterior.

Con la función ob_end_clean limpiamos el búfer para evitar errores y liberar memoria ;).

Y por último, con la función base64_encode que nos permite convertir nuestra imagen en memoria a un formato que pueda aceptar el campo de tipo blob de Mysql.

En este punto, ya podemos guardar nuestra imagen en la base de datos en un campo de tipo blob. No voy a explicar como hacer esta parte, pues ya  sabemos como guardar otro tipo de datos; el procedimiento es el mismo.

Ahora bien, para mostrarla, hacemos nuestra consulta a base de datos como de costumbre, lo único que cambia es la línea de código que viene a  continuación:


echo '<_img src="' . Imagenes::mostrarBlob ( $miImagen->getImagen () ) . '"/>';


Donde Imagenes es una clase abstracta que contiene la función que expliqué anteriormente y esta nueva que es mostrarBlob.$miImagen, es un objeto que contiene la consulta realizada a la base de datos, y el método getImagen devuelve especificamente la imagen blob
de la consulta.

Pero quien es esa función mostrarBlob?, pues aquí la tenemos.


public static function mostrarBlob ( $blob ) {

 $mime = Archivos::obtenerMimeTypeBlob ( $blob );
 return "data:" . $mime . ";base64," . $blob;
}


La cosa se nos esta complicando un poco, pero no importa, que lo que interesa aquí es aprender.

Ahora bien, para mostrarla correctamente, necesitamos saber el tipo de imagen a mostrar, que si bien sabemos que es de tipo png, el sistema no lo sabe. Para eso hacemos uso de una función que nos va a permitir el cometido.

Pero antes, saber que Archivos, es otra clase que agrupa funciones que permiten procesar archivos de diferentes tipos y el método obtenerMimeTypeBlob permite obtener el MIMETYPE de archivos guardados en base de datos con formato blob.

Por último, la línea de código return "data:" . $mime . ";base64," . $blob;
donde "data:" permite identificar el tipo de imagen (realmente el tipo de archivo), ";base64," nos permite indicar la codificación de nuestro dato blob y $blob el dato de la consulta.

Pero quien es obtenerMimeTypeBlob?, aquí su código:


public static function obtenerMimeTypeBlob ( $blob ) {
 $listaFirmas = array (
 "474946383761"=>"image/gif",
 "474946383961"=>"image/gif",
 "89504E470D0A1A0A"=>"image/png",
 "FFD8FFE0"=>"image/jpeg",
 "FFD8FFE1"=>"image/jpeg",
 "FFD8FFE8"=>"image/jpeg",
 "25504446"=>"application/pdf",
 "377ABCAF271C"=>"application/zip",
 "504B0304"=>"application/zip",
 );

 $blob = base64_decode ( $blob );

 $firma = substr ( $blob, 0, 60 );
 $firma = array_shift ( unpack ( "H*", $firma ) );

 foreach ( $listaFirmas as $firmaParcial => $Mime ) {

 if ( stripos ( $firma, $firmaParcial ) === 0 ) {

 return $Mime;
 }
 }
 return "application/octet-stream";
 }


Lo que hace esta función, es leer nuestro blob y obtener las coincidencias para los tipos de archivos indicados en el arreglo $listaFirmas,  solo lo he hecho para estos pocos archivos, pero es un comienzo ;). Al encontrar el mime correspondiente lo devuelve, si no, devuelve un tipo de mime genérico.

Pues bien, si piensan que la cosa está muy complicada porque utilizo muchas clases y no las hé colocado todas o completas, no es problema porque  si las metemos todas en una sola clase, igual funcionará este ejemplo sin ningún problema, pero de todas formas aquí les dejo una clase completa con todas las funciones necesarias :).


abstract class ManejoBlob {

 /**
 * Convierte un archivo png en formato binario.
 *
 * @param string $archivo Url de la imagen.
 * @return binary Objeto de tipo blob.
 */
 public static function pngABlob ( $archivo ) {

 $imagenCreada = imagecreatefrompng ( $archivo );

 if ( imagealphablending ( $imagenCreada, true ) ) {//SI SE ESTABLECE EL CANAL ALPHA

 imagesavealpha ( $imagenCreada, true );
 }
 ob_start ();
 imagepng ( $imagenCreada );
 $imagen = ob_get_contents ();
 ob_end_clean ();
 return base64_encode ( $imagen );
 }

 /**
 * Muestra un dato de tipo blob.
 *
 * @param binary $blob Dato de tipo blob.
 */
 public static function mostrarBlob ( $blob ) {

 $mime = Archivos::obtenerMimeTypeBlob ( $blob );
 return "data:" . $mime . ";base64," . $blob;
 }

 /**
 * Obtiene el mime type de un tipo de dato blob.
 *
 * @param binary $blob Dato de tipo blob.
 */
 public static function obtenerMimeTypeBlob ( $blob ) {
 $listaFirmas = array (
 "474946383761"=>"image/gif",
 "474946383961"=>"image/gif",
 "89504E470D0A1A0A"=>"image/png",
 "FFD8FFE0"=>"image/jpeg",
 "FFD8FFE1"=>"image/jpeg",
 "FFD8FFE8"=>"image/jpeg",
 "25504446"=>"application/pdf",
 "377ABCAF271C"=>"application/zip",
 "504B0304"=>"application/zip",
 );

 $blob = base64_decode ( $blob );

 $firma = substr ( $blob, 0, 60 );
 $firma = array_shift ( unpack ( "H*", $firma ) );

 foreach ( $listaFirmas as $firmaParcial => $Mime ) {

 if ( stripos ( $firma, $firmaParcial ) === 0 ) {

 return $Mime;
 }
 }
 return "application/octet-stream";
 }
}


PD. ¿Por qué la clase es de tipo abstract?, porque no requiere ser instanciada y así ahorramos memoria ;P

Hasta una próxima oportunidad.