martes, 31 de marzo de 2009

Cambio climático


Este fin de semana medio globo ha apagado sus luces en busca de una concienciación global sobre el problema del calentamiento y el derroche de medios y recursos - léase consumismo- en que estamos inmersos, primordialmente, los países del denominado primer mundo.

Desgraciadamente este no es un problema nuevo, como podemos ver en el vídeo en el que una Severn Suzuki de tan sólo 12 años lo deja claro con la lectura de su manifiesto ante la ONU. Peor aún es que el discurso fue pronunciado en el año 1992 pero sigue igual de vigente hoy en día. En cualquier caso lo reconfortante -si es que hay algo- es que exista gente tan comprometida y con las ideas tan claras desde tan jóvenes -a algunos nos ha costado bastante más tiempo buscar el "sentido de la vida", otros sólo lo hayamos con la ayuda de los Monty Python-. Más reconfortante todavía resulta el hecho de que todavía siga en la brecha.

*gracias Ángel.

Enlaces:
Severn Cullis en la wikipedia: http://es.wikipedia.org/wiki/Severn_Cullis-Suzuki

domingo, 29 de marzo de 2009

Eliminar objetos de una imagen con ImageCompletion



Como se puede ver en el ejemplo superior, sacado de la propia página del proyecto ImageCompletion, cuando queremos sacar un objeto de una fotografía, podemos pasarnos un par de horas cacharreando con gimp o photoshop para intentar obtener un resultado que probablemente no será tan bueno como el que haríamos automáticamente empleando el programa libre ImageCompletion.

Para su utilización, lo único que tenemos que hacer es marcar de un color sólido el objeto que queremos "eliminar" para que, a partir del resto de la imagen, el programa interpole de modo automatizado los píxeles necesarios para sobrescribir el color con el que hemos marcado la zona a eliminar y que parezca que no se ha tocado la foto.

Los únicos requisitos para su ejecución son Windows XP y tener instalado la versión 1.1 del framework .net.

Enlaces:
Descarga y manuales de ImageCompletion: http://www2.mta.ac.il/~tal/ImageCompletion/

Manual de PHP 70.MySQL: Campos y conexiones

Conexión con el servidor de bases de datos

Antes de empezar a trabajar con bases de datos es imprescindible que ambos servidores –Apache y MySQL– estén activos.

Como paso inmediato hemos de interconexionar ambos servidores de forma que sea posible tranferir información de uno a otro.

Para ello es necesario utilizar siempre una función PHP con la siguiente sintaxis:

$c=mysql_connect(h, u, p)

donde $c es la variable que recoge el identificador del enlace, h es la dirección del servidor de bases de datos, ("localhost") , u es el nombre de uno de los usuarios registrados en la tabla user ("pepe" o "root") y p la contraseña (en nuestro caso "pepa" ó "") .

Estos tres valores –cadenas de texto– deben ir escritos entre comillas.

Para cerrar la conexión, tenemos que insertar:

$c=mysql_close ($c)

donde $c es el nombre de la variable en la que se recogió el indentificador del enlace en el momento de la apertura.

Aquí tienes el código de un script que realiza la apertura de una conexión y después la cierra.:

if(
$c=mysql_connect("localhost","pepe","pepa")){
print
"
La conexión con el servidor de bases de datos se ha realizado con exito
"
;
}else{
print
"
No ha podido realizarse la conexión
"
;
}

if(
mysql_close($c)){
print
"
Se ha cerrado la conexión con el servidor de bases de datos
"
;
}



Y aquí puedes comprobar el funcionamiento del script anterior.

Si realizáramos una segunda conexión (con los mismos argumentos) sin haber cerrado la anterior no se efectuará un nuevo enlace sino que nos devolverá el ya abierto.

Sintaxis alternativa

Otra forma de efectuar la conexión es utilizar los valores registrados en el fichero mysql.inc.php –lo hemos creado en la página anterior– y eso requiere que insertemos un include("c:..."), indicando la ruta completa de seguridad y el nombre del fichero en el que hemos guardado las claves y que era mysql.inc.php.

En este supuesto como valores de los parámetros h, u y p pondremos los nombres de las variables:
$mysql_server
$mysql_login y
$mysql_pass
sin encerrarlas entre comillas.

Aquí tienes el código de un script que realiza la apertura de una conexión y después la cierra:

include("C:/Apache/seguridad/mysql.inc.php");
if(
$c=mysql_connect($mysql_server,$mysql_login,$mysql_pass)){
print
"
La conexión con el servidor de bases de datos se ha realizado con exito
"
;
}else{
print
"
No ha podido realizarse la conexión
"
;
exit();
}

if(
mysql_close($c)){
print
"
Se ha cerrado la conexión con el servidor de bases de datos
"
;
}


Desde este enlace puedes comprobar su funcionamiento.

La instrucción OR DIE

Es esta una buena ocasión para hablar de una instrucción PHP que no hemos mencionado hasta el momento.

Es una opción alternativa a exit() que, como acabamos de ver en un ejemplo, interrumpe la ejecución de un script en el momento de ser ejecutada.

Cuando se produce un error en la ejecución de un script –no poder establecer conexión con MySQL, por ejemplo– no tiene sentido seguir ejecutándolo. Lo razonable será interrumpir el proceso y advertir del error.

Si añadimos a la instrucción $c=mysql_conect('h','u','p') (sin paréntesis, ni comas, ni punto y coma, sólo separado por un espacio):

or die ('mensaje')

y ponemos el punto y coma de fin de instrucción después de cerrar este último paréntesis, en el caso de que se produzca un error se interrumpirá la ejecución del script y apare- cerá en la ventana del navegador el texto incluido en mensaje.

Este es el código fuente de un script que produce un error –la contraseña es incorrecta– y que utiliza esta nueva sintaxis:

$c=mysql_connect("localhost","pepe","pepi") or die("No se conecto");

if(
mysql_close($c)){
print
"
Se ha cerrado la conexión con el servidor de bases de datos
"
;
}


Pero si lo ejecutas verás que aparece un mensaje de error generado por PHP.

Este tipo de mensajes pueden deshabilitarse haciendo una modificación en php.ini. Pero hay una técnica mucho más fácil. Bastará con insertar delante de la función una arroba (@) para evitar que aparezcan. En este otro script lo hemos incorporado y puedes comprobarlo aqui:

$c=@mysql_connect("localhost","pepe","pepi") or die("No se conecto");

if(
mysql_close($c)){
print
"
Se ha cerrado la conexión con el servidor de bases de datos
"
;
}


Lista de bases de datos existentes

Antes de crear y/o borrar una base de datos puede ser conveniente y útil comprobar si ya existe.

PHP dispone de herramientas para conocer el número de bases de datos existentes en el servidor, así como sus nombres. Todas ellas requieren que se haya establecido una conexión con el servidor.

$p=mysql_list_dbs($c)

La variable $p es un nuevo identificador imprescindible y previo a la determinación del número y los nombres de las bases de datos existentes en el enlace abierto (identificado por $c).

$n=mysql_num_rows($p)

Esta función devuelve el número de bases de datos existentes en el servidor.

Utiliza como parámetro ($p) el resultado obtenido mediante la función anterior.

Ese número puede recogerse en una variable (en este caso $n).

mysql_db_name($p, i)

Esta nueva función devuelve el nombre de una de las bases de datos, identificada por un número i que debe pertenecer al intervalo [0,$n).

Fíjate que i tiene que ser i<$n porque si, por ejemplo, $n=5 los cinco valores posibles de i serían: 0,1,2,3 y 4.

Una lista completa de todas las bases de datos existentes en el servidor podría hacerse mediante el siguiente proceso:

Abrir la conexión.
Invocar a mysql_list_dbs.
Contar el número de bases de datos con mysql_num_rows
• Insertar un bucle:
for ($i=0;$i<$num,$i++)
• Presentar la lista de nombres mediante un bucle que lea los diferentes valores de $i en:
mysql_db_name($p,$i)

Aquí tienes el código fuente de un ejemplo completo:


<?

if($c=mysql_pconnect ("localhost","pepe","pepa")){

echo "<h2> Conexión establecida con el servidor</h2><br>";

# recoge en una nueva variable que hemos llamado $p

# un nuevo identificador, $p

$p=mysql_list_dbs($c);

# utilizando ese nuevo identificador podemos extraer el número

$numero=mysql_num_rows($p);

echo "Hay ",$numero, " bases de datos en el servidor<br>" ;





#este bucle (desde cero hasta el número

# nos irá listando los nombres correspondientes a esos numeros de orden



for ($i=0;$i<$numero;$i++) {

echo mysql_db_name($p, $i),"<br>";



}





if(mysql_close($c)){

echo "<h2> Conexión cerrada con exito</h2><br>";



}else{

echo "<h2> No se ha cerrado la conexión</h2>";

};

}else{

echo "<h2> NO HA SIDO POSIBLE ESTABLECER LA CONEXIÓN</h2>";

}

?>







y desde aquí puedes ejecutarlo

Crear una base de datos

La creación de una base de datos también requiere una conexión previa y utiliza la siguiente sintaxis:

mysql_query ("CREATE DATABASE nom")

donde nom es el nombre de la nueva base de datos.

Esta función devuelve TRUE si la base de datos es creada, y FALSE si no es posible hacerlo.

Si intentamos crear una base de datos con un nombre ya existente la función nos devolverá FALSE.

Aquí tienes el código de un ejemplo de creación de una base de datos:


<?

if($conexion=mysql_connect ("localhost","pepe","pepa")){

echo "<h2> Conexión establecida con el servidor</h2><br>";

if(mysql_query("CREATE DATABASE otraBase")){

echo "<h2> Base de datos creada</h2><br>";

}else{

echo "<h2> No ha sido posible crear la base de datos</h2><br>";

};



if(mysql_close($conexion)){

echo "<h2> Conexión cerrada con exito</h2><br>";

echo "El identificador de conexion es:",$conexion;

}else{

echo "<h2> No se ha cerrado la conexión</h2>";

};

}else{

echo "<h2> NO HA SIDO POSIBLE ESTABLECER LA CONEXIÓN</h2>";

}

?>


Si lo ejecutas dos veces podrás comprobar que en la segunda oportunidad te aparece el mensaje diciendo que no ha sido posible crearla.

Borrar una base de datos

Para borrar una base de datos se requiere el uso de la siguiente función PHP:

mysql_query ("DROP DATABASE nom")

donde nom es el nombre de la base de datos y debiendo ponerse toda la cadena del paréntesis entre comillas.

Esta función devuelve TRUE cuando se ejecuta con éxito, y FALSE en el caso contrario.

Este es el código de un script que puede borrar la base creada anteriormente:


<?

if($c=mysql_connect ("localhost","pepe","pepa")){

echo "<h2> Conexión establecida con el servidor</h2><br>";

if(mysql_query ("DROP DATABASE otraBase",$c)){

echo "<h2> Base de datos borrada</h2><br>";

}else{

echo "<h2> No ha sido posible BORRAR la base de datos</h2><br>";

};



if(mysql_close($c)){

echo "<h2> Conexión cerrada con exito</h2><br>";

echo "El identificador de conexion es:",$conexion;

}else{

echo "<h2> No se ha cerrado la conexión</h2>";

};

}else{

echo "<h2> NO HA SIDO POSIBLE ESTABLECER LA CONEXIÓN</h2>";

}

?>



Igual que ocurría al tratar de crearla, si intentamos borrar una base de datos inexistente la función mysql_drop_db nos devolverá FALSE.

Depurando los procesos de creación y borrado de bases de datos

Cuando intentamos crear una base de datos ya existente o borrar una inexistente las funciones mysql_query nos devuelven FALSE pero esa respuesta no nos dice la causa por la que no ha sido posible la ejecución de la instrucción.

Sería mucho más interesante comprobar la existencia o inexistencia de una base de datos antes de ejecutar esas instrucciones y que después de la comprobación se nos presentara un mensaje informativo.

MySQL dispone de una sentencia para este fin, pero –aunque la vamos ver más adelante– olvidémosnos de su existencia e intentemos crear nuestro propio script de comprobación.

Combinando las instrucciones anteriores no resulta difícil hacerlo. Aquí tienes un ejemplo de código para efectuar esa comprobación al crear una base de datos:


<?

# introducimos en una variable el nombre de la base de datos a crear



$crear="mispruebas";



#conectamos con el servidor y comprobamos la conexión



if ($conexion=mysql_pconnect ("localhost","pepe","pepa")){

echo "<h2> Conexión establecida con el servidor</h2><br>";

$p=mysql_list_dbs($conexion);



$numero=mysql_num_rows($p);

$comprueba=0;



#comprobamos si existe una base con ese nombre

# si existe hace la variable comprueba igual a 1

# si no existe la variable comprueba sera 0 tal como la hemos

# puesto aquí arriba



for ($i=0;$i<$numero;$i++) {

if ($crear==mysql_db_name($p, $i)){

$comprueba=1;

};

}



#si la base de datos no existe la creamos y escribimos el mensaje de exito

#si existe, avisamos de su existencia y evitamos intentar crearla

# observa que como nombre del la nueva base puede ponerse una variable



if($comprueba==0){

if(mysql_query ("CREATE DATABASE $crear")){

echo "<h2> Base de datos $crear creada</h2><br>";

}else{

echo "<h2> No ha sido posible crear la base de datos $crear</h2><br>";

};

}else{

echo "<h2> La base de datos $crear YA EXISTE</h2><br>";

} ;



# cerramos la conexión con el servidor



if(mysql_close($conexion)){

echo "<h2> Conexión cerrada con exito</h2><br>";

}else{

echo "<h2> No se ha cerrado la conexión</h2>";

};



}else{

echo "<h2> NO HA SIDO POSIBLE ESTABLECER LA CONEXIÓN</h2>";

}

?>



y este otro código es para el caso de borrado:


<?

# introducimos en una variable el nombre de la base de datos a borrar



$borrar="mispruebas";



#conectamos con el servidor y comprobamos la conexión



if ($conexion=mysql_connect ("localhost","pepe","pepa")){

echo "<h2> Conexión establecida con el servidor</h2><br>";

$p=mysql_list_dbs($conexion);



$numero=mysql_num_rows($p);

$comprueba=0;



#comprobamos si existe una base con ese nombre

# si existe hace la variable comprueba igual a 1

# si no existe la variable comprueba sera 0 tal como la hemos

# puesto aquí arriba



for ($i=0;$i<$numero;$i++) {

if ($borrar==mysql_db_name($p, $i)){

$comprueba=1;

};

}



#si la base de datos existe la borramos y escribimos el mensaje de exito

#si no existe, avisamos de su inexistencia y evitamos intentar borrarlas

# observa que como nombre del la nueva base puede ponerse una variable



# AHORA BORRAREMOS SOLO EN EL CASO DE QUE EXISTA

# que significa que $comprueba es igual a 1



if($comprueba==1){

if(mysql_query ("DROP DATABASE $borrar")){

echo "<h2> Base de datos $crear BORRADA</h2><br>";

}else{

echo "<h2> No ha sido posible BORRAR LA BASE de datos $borrar</h2><br>";

};

}else{

echo "<h2> La base de datos $borrar NO EXISTIA</h2><br>";

} ;



# cerramos la conexión con el servidor



if(mysql_close($conexion)){

echo "<h2> Conexión cerrada con exito</h2><br>";

}else{

echo "<h2> No se ha cerrado la conexión</h2>";

};



}else{

echo "<h2> NO HA SIDO POSIBLE ESTABLECER LA CONEXIÓN</h2>";

}

?>



- en realidad lo ideal sería cambiar los for por un while (($i<$numero) && (! comprueba)) - Experimenta con estos scripts, sustitúyelos por otros propios en los que utilices las funciones que hemos incluido –a la derecha tienes el código fuente– dentro del fichero mysql.inc.php y comprueba, listando las bases de datos existentes, que sólo queden: mysql y test.

Tipos de campos MySQL

Conocidos los procesos de creación, listado y borrado de bases de datos ya estamos en disposición en empezar a tratar lo relativo a las tablas.

Es muy necesario conocer los diferentes tipos de campos que pueden contener las tablas de MySQL -podrás encontrarlos al final del documento-.

Conocer las posibilidades de cada uno será fundamental a la hora de diseñar una tabla. En ese momento tendremos que decidir qué campos son necesarios, cuál es tipo requerido, cuáles han de ser sus dimensiones y también cuáles de ellos requerirán ser tratados como índices.

Tipos de campo bien elegidos y un tamaño adecuado a las necesidades reales de nuestro proyecto son las mejores garantías para optimizar el tamaño de la tabla y para hacerla realmente eficaz.

El grado de eficiencia de una base de datos suele ser directamente proporcional al tiempo invertido en el análisis de la estructura de sus tablas.

CREACIÓN DE LAS BASES DE DATOS NECESARIAS PARA EL CURSO

Una vez hayas hecho todas las pruebas necesarias con las funciones anteriores, llega el momento de utilizarlas para crear las bases de datos que vamos a utilizar en el Curso.

Pulsa en este enlace para que cree automáticamente la base de datos que va a contener los sucesivos ejemplos que hemos incluido en estos materiales.

Crear base de datos EJEMPLOS


Una vez hecho esto, escribe tu propio script y crea una segunda base de datos como el nombre practicas. Esta será la que habrás de utilizar en ejercicios que tendrás que ir haciendo en el resto del curso.


¡Cuidado!

Antes de continuar, es conveniente comprobar desde Windows que el directorio c:\mysql\data contiene las bases de datos ejemplos y practicas


Automatizar la conexión


Con nuestros conocimientos sobre PHP ya estamos en condiciones de hacer más cómoda la conexión. Creemos una función que realice de forma automática la conexión con MySQL y guardémosla en nuestro fichero mysql.inc.php

<?
# estas son las variables anteriores
$mysql_server="localhost";
$mysql_login="pepe";
$mysql_pass="pepa";


# creemos una nueva variable $c sin asignarle ningún valor
# para que pueda recoger el identificador de conexión
# una vez que se haya establecido esta

$c;
# escribamos la función que hace la conexión
# como pretendemos que el valor del identificador
# sea usado fuera de la función, para recuperar su valor
# pasaremos ese valor por referencia anteponiendo & al
# nombre de la variable
function conecta1(&$c){
# para usar las variables anteriores en la funcion
# hemos de definirlas como globales
global $mysql_server, $mysql_login, $mysql_pass;
if($c=mysql_connect($mysql_server,$mysql_login,$mysql_pass)){
print "&ltbr>Conexión establecida<br>";
}else{
print "<br>No ha podido realizarse la conexión<br>";

# el exit lo incluimos para que deje de ejecutarse
# el script si no se establece la conexión
exit();
}
}

# esta función asignará a $c el valor del identificador

# repetimos la misma función con otro nombre
# ahora quitaremos el mensaje de conexión establecida
# consideraremos que si no hay mensaje se ha establecido
# asi quedará limpia nuestra página

function conecta2(&$c){
global $mysql_server, $mysql_login, $mysql_pass;
if($c=mysql_connect($mysql_server,$mysql_login,$mysql_pass)){
}else{
print "<br>No ha podido realizarse la conexión<br>";
exit();
}
}

?>

Si sustituyes el contenido de tu mysql.inc.php por el que tienes aquí arriba –puedes eliminar la líneas de comentario al hacerlo– estaremos en disposición de ejecutar scripts como este.

En este ejemplo utilizaremos la primera función:



Ver código fuente
ejemplo153.php


y ahora haremos uso de la segunda



Ver código fuente Ejecutar ejemplo




Tipos de campos en MySQL


MySQL tiene habilitados diversos tipos de campos que en una primera aproximación podrían clasificarse en tres grupos:


  • Campos numéricos
  • Campos de fecha
  • Campos de cadenas de caracteres


Campos numéricos


MySQL soporta los tipos numéricos exactos(INTEGER, NUMERIC, DECIMAL, y SMALLINT) y los tipos numéricos aproximados (FLOAT, DOUBLE precision y REAL).


Los campos que contienen números enteros admiten el parámetro UNSIGNED, que implica que no admita signos, por lo que solo aceptaría enteros positivos.


Todos los campos numéricos admiten el parámetro ZEROFILL cuya función es completar el campo con ceros a la izquierda hasta su longitud máxima.




Tipos de campos numéricos enteros


Estos son los distintos tipos de campos numéricos enteros que admite MySQL. Los parámetros señalados entre corchetes son opcionales.



TINYINT [(M)] [UNSIGNED] [ZEROFILL]

Número entero muy pequeño. Con la opción UNSIGNED puede tomar valores entre 0 y 255. En caso contrario, puede estar comprendido entre -128 y 127.

El parámetro ZEROFILL sólo tiene sentido junto con la opción UNSIGNED ya que no es habitual rellenar los números negativos con ceros a la izquierda del signo.

El valor por defecto de parámetro M (número de cifras) es 4 si no está activada la opción UNSIGNED. Si esta opción estuviera activada el valor por defecto sería M=3. Para valores de M >valor por defecto reajusta el tamaño al valor por defecto.

Si se asigna a M un valor menor que cuatro limita el número de caracteres al tamaño especificado considerando el signo sólo en los números negativos.

Por ejemplo, si M=3 admitiría 148, pero si intentamos insertar -148 recortaría por la izquierda y solo insertaría -14.

Si intentamos insertar un valor fuera de rango registraría el valor dentro del rango más próximo a él.
P. ej.: Si tratamos de insertar el valor 437 escribiría 127 ó 255, este último en el caso de tener la opción UNSIGNED.
Si pretendiéramos insertar -837 con la opción UNSIGNED escribiría 0 y sin ella pondría -128.

El tamaño de un campo TINYINT es de 1 byte.

SMALLINT [(M)] [UNSIGNED] [ZEROFILL]

Número entero pequeño. Con la opción UNSIGNED puede tomar valores entre 0 y 65 535. En caso contrario, puede estar comprendido entre -32 768 y 32 767.

Son válidos los comentarios hechos para TINYINT, excepto los relativos a los valores por defecto de M que en este caso serían 6 ó 5. Su tamaño es de 2 bytes.

MEDIUMINT [(M)] [UNSIGNED] [ZEROFILL]

Número entero mediano. Con la opción UNSIGNED puede tomar valores entre 0 y 16 777 215. En caso contrario, puede estar comprendido entre -8 388 608 y 8 388 607.

También son válidos los comentarios hechos para TINYINT, excepto los relativos al valor por defecto de M que en este caso serían 8. Su tamaño es de 3 bytes.

INT [(M)] [UNSIGNED] [ZEROFILL]

Número entero. Con la opción UNSIGNED puede tomar valores entre 0 y 4 294 967 295. En caso contrario, puede estar comprendido entre -2 147 483 648 y 2 147 483 647.

Son válidos todos los comentarios de los casos anteriores. Su tamaño es de 4 bytes.

INTEGER [(M)] [UNSIGNED] [ZEROFILL]

Es un sinónimo de INT

BIGINT [(M)] [UNSIGNED] [ZEROFILL]

Número entero grande. Con la opción UNSIGNED puede tomar valores entre 0 y 18 446 744 073 709 551 615. En caso contrario, puede estar comprendido entre -9 223 372 036 854 775 808 y 21 474 839 223 372 036 854 775 807 647, pero al usarlo desde PHP estará sujeto a las limitaciones máximas de los valores numéricos de este.

Son válidos todos los comentarios de los casos anteriores. Su tamaño es de 8 bytes.

Números de coma flotante

Por la estructura binaria de los microprocesadores y habida cuenta de que algunos números no enteros -sin ir más lejos, el 0.1- requerirían infinitos caracteres binarios para su representación exacta, se hace necesario introducir un redondeo en su tratamiento informático y como consecuencia de ello asumir que se generan errores de medida.

Esta circunstancia obligó al tratamiento de los números decimales mediante el llamado Standar de Aritmética de Punto Flotante, un algoritmo definido por la IEEE (Institute of Electrical and Electronics Engineers) que unificó los procesos de representación de números en ordenadores con lo que son uniformemente controlables los errores introducidos.

El Standar de Aritmética de Punto Flotante estableció dos niveles de precisión:
  • Precisión Simple, en la que todo número debe ser almacenado en 32 bits
    (4 bytes)
  • Doble precisión, en la que los números se almacenan en 64 bits (8 bytes).
MySQL admite los siguientes tipos de números de coma flotante:


FLOAT(x) [ZEROFILL]

Número de coma flotante. Ignora la opción UNSIGNED, pero sí acepta ZEROFILL, por lo que debe prestarse atención a estas opciones ya que no sería demasiado habitual una presentación como esta: 000-3.47

El valor de x especifica la precisión. Si x<=24 será de precisión simple. cuando 24 lo convertirá automáticamente a doble precisión.

Cuando no se especifica el valor de x considera el campo como de precisión simple. Su tamaño es de 4 bytes si x<=24 y de 8 bytes cuando 24

FLOAT [(M,D)] [ZEROFILL]

Número de coma flotante de precisión simple. Son válidos los comentarios relativos a las opciones UNSIGNED y ZEROFILL del caso anterior.

Toma valores en los intervalos siguientes:
  • -3.402823466E+38 a -1.175494351E-38
  • 0 y
  • 1.175494351E-38 a 3.402823466E+38.
M es la anchura máxima de visualización y D es el número de decimales. Si M > 24 se convierte automaticamente a doble precisión
FLOAT sin argumentos representa un número de coma flotante y precisión simple.

DOUBLE [(M,D)] [ZEROFILL]

Número de coma flotante de doble precisión. Siguen siendo válidos los comentarios relativos a las opciones UNSIGNED y ZEROFILL del caso anterior.

Toma valores en los intervalos siguientes:
  • -1.7976931348623157E+308 a -2.2250738585072014E-308
  • 0 y
  • 2.2250738585072014E-308 a 1.7976931348623157E+308
M es la anchura máxima de visualización y D es el número de decimales.

DOUBLE sin argumentos representa un número de coma flotante y precisión doble.

REAL [(M,D)] [ZEROFILL]

Es sinónimo de DOUBLE.

DECIMAL [(M[,D])] [ZEROFILL]

Es un número de coma flotante y doble precisión que se almacena como un campo de tipo CHAR.

El valor es guardado como una cadena donde cada carácter representa una cifra. La coma y el signo menos de los números negativos no son tenidos en cuenta en el valor de M -anchura máxima de visualización- aunque si se reserva -automáticamente- espacio para ellos en campo.
Si D vale 0 no tendrá parte decimal. Los números toman valores en el mismo intervalo especificado para DOUBLE.

Los valores por defecto de M y D son respectivamente 10 y 0.
Ocupan M+2 bytes si D > 0; M+1 bytes si D = 0 ó D+2 bytes si M <>

NUMERIC(M,D) [ZEROFILL]

Se comporta de forma idéntica a DECIMAL


Campos de fecha

MySQL dispone de campos específicos para el almacenamiento de fechas. Son los siguientes:

DATE

Recoge una fecha dentro del intervalo 01-01-1000 a 31-12-9999. MySQL guarda los valores DATE con formato AAAA-MM-DD (año-mes-día) . Su tamaño es de 3 bytes.

DATETIME

Recoge una combinación de fecha y hora dentro del intervalo 00:00:00 del día 01-01-1000 y las23:59:59 del día 31-12-9999. MySQL guarda los valores DATETIME con formato AAAA-MM-DD HH:MM:SS (año-mes-día hora:minutos:segundos) . Su tamaño es de 8 bytes.

TIME

Recoge una hora dentro del intervalo -838:59:59 a 838:59:59. MySQL guarda los valores TIME con formato HH:MM:SS (horas:minutos:segundos) . Su tamaño es de 3 bytes.

YEAR 0 YEAR(2) o YEAR(4)

Recoge un año en formato de cuatro cifras (YEAR o YEAR(4)) o en formato de dos cifras (YEAR(2))dentro del intervalo 1901 a 2155 en el caso de cuatro cifras o de 1970 a 2069 si se trata de dos cifras. Su tamaño es de 1 byte.

TIMESTAMP [(M)]

Recoge un tiempo UNIX. El intervalo válido va desde 01-01-1970 00:00:00 a cualquier fecha del año 2037.

El parámetro M puede tomar los valores: 14 (valor por defecto), 12, 8, o 6 que se corresponden con los formatos AAAAMMDDHHMMSS, AAMMDDHHMMSS, AAAAMMDD, o AAMMDD.
Si se le asigna la opción NUL guardará la hora actual. Cuando se asigna 8 o 14 como parámetros es considerado como un número y para las demás opciones como una cadena.

Independientemente del valor del parámetro, un campo TIMESTAMP siempre ocupa 4 bytes.

Campos tipo cadena de caracteres

CHAR (M) [BINARY]

Es una cadena de tamaño fijo que se completa a la derecha por espacios si es necesario.

El parámetro M puede valer de 1 a 255 caracteres.

Los espacios finales son suprimidos cuando la cadena es insertada en el registro.

Los valores de tipo CHAR son elegidos y comparados sin tener en cuenta Mayúsculas / Minúsculas y utilizan el juego de carácteres por defecto.

Se puede utilizar el operador BINARY para hacer la cadena sensible a Mayúsculas / Minúsculas.

Se puede utilizar un campo tipo CHAR(0) con el atributo NULL para almacenar una valor booleano. En este caso ocupará un solo byte y podrá tener únicamente dos valores: NUL ó \"\".

Su tamaño es de M bytes siendo 1 <= M <= 255 .

VARCHAR(M) [BINARY]

Es una cadena de caracteres de longitud variable. Su tamaño máximo -especificado en el parámetro M- puede estar comprendido entre 1 y 255 caracteres. Con la opción BINARY es capaz de discriminar entre Mayúsculas / minúsculas.

TINYBLOB o TINYTEXT

TINYBLOB y TINYTEXT son cadenas de caracteres de longitud variable con un tamaño máximo de 255 (28 - 1) caracteres.

La diferencia entre ambas es que TINYBLOB discrimina entre Mayúsculas / minúsculas, mientras que TINYTEXT no lo hace.

Ninguno de los campos BLOB y TEXT admite valores por DEFECTO

Las versiones de MySQL anteriores a 3.23.2 permiten utilizar estos campos para indexar.

Si se intenta guardar en un campo de este tipo una cadena de mayor longitud que la especificada solamente se guardarán los M primeros caracteres de la cadena.

BLOB o TEXT

BLOB y TEXT son cadenas de caracteres de longitud variable con un tamaño máximo de 65535 (216 - 1) caracteres.

La diferencia entre ambas es que BLOB si discrimina entre Mayúsculas / minúsculas, mientras que TEXT no lo hace.

Ninguno de los campos: BLOB y TEXT admite valores por DEFECTO


MEDIUMBLOB o MEDIUMTEXT

MEDIUMBLOB y MEDIUMTEXT son cadenas de caracteres de longitud variable con una longitud máxima de 16.777.215 (224 - 1) caracteres.
Son válidas las especificaciones hechas en el apartado anterior.

El tamaño máximo de los campos de este tipo está sujeto a limitaciones externas tales como la memoria disponible y el tamaño del buffer de comunicación servidor/cliente.


LONGBLOB o LONGTEXT

Su única diferencia con la anterior es el tamaño máximo de la cadena, que en este caso es 4.294.967.295 (232 - 1) caracteres.

ENUM(\'valor1\',\'valor2\',...)

Es una cadena de caracteres que contiene uno solo de los valores de la lista (valor1, valor2, etc. etc.).

A la hora de insertar un nuevo registro en una tabla, el valor a especificar para un campo de este tipo ha de ser una cadena que contenga uno de los valores especificados en la tabla. Si se tratara de insertar un valor distinto de ellos insertaría una cadena vacía.

SET(\'valor1\',\'valor2\',\'valor3\'...)

Es una cadena de caracteres formados por la unión de ninguno, uno o varios de los valores de una lista. El máximo de elementos es 64.

Los valores que deben escribirse en los campos de este tipo han de ser numéricos, expresados en forma binaria o en forma decimal.

En el supuesto de que contuviera tres valores los posibles valores a insertar en un campo de este tipo a la hora de añadir un registro serían los siguientes.

Incluir valoresCódigo valorCadena
binaria
Equiv.
decimal
val1val2val3val1val2val3
Si 1 11111 7
Si No 1 10011 3
Si No 1 01101 5
No 0 11110 6
No No 0 01100 4
No NO 0 10010 2
Si NoNo 1 00001 1
No NoNo 0 00000 0







Fuente:


Manual de PHP 69. MySql. Ficheros MySQL

La aplicación MySql

Una de las opciones más útiles de PHP es la posibilidad de gestionar bases de datos en ordenadores remotos.

Existen multitud de programas de servidores de bases de datos y PHP dispone de funciones para el manejo de muchos de ellos tales como:

  • FilePro
  • dBase
  • DBM
  • Microsoft SQL
  • PostgreSQL
  • mSQL
  • InterBase
  • MySQL
Nuestra opción por MySQL obedece a que es uno de los gestores de bases de datos SQL más populares, es muy eficiente y, además, es gratuito (Open Source).

El sintagma SQL es el acrónimo de Structured Query Language, es decir, Lenguaje estructurado de consultas.

Bases de datos y tablas

Como verás más adelante, una base de datos no es otra cosa que un directorio que contiene tablas.

Las tablas son las que contienen los datos y en consecuencia son el elemento verdaderamente importante, dado que no es demasiado relevante que esos datos estén en uno u otro directorio, lo verdaderamente importante es que estén y que sean accesibles y manejables.

Si es este tu primer contacto con el mundo de las bases de datos, quizá sea importante conocer su argot ya que en adelante tendremos que referirnos a tablas, campos, registros e índices y quizá no esté de más explicar un poco esas ideas.

Pensemos en la base de datos –directorio– como un armario archivador de nuestro Centro e imaginemos que dentro de él hay una serie de cajonestablas– en los que se puede guardar una buena cantidad de documentos con formato idéntico –registros– tales como: matrículas, fichas de alumnos, etcétera.

Cada uno de estos tipos de documento tendría las mismas casillascampos–, con la única diferencia de que los datos contenidos en esos campos –de igual forma, dimensión y tamaño en todos los registros– serían los que diferenciarían un documento de otro.

En una tabla MySQL el fichero con extensión .frm contiene precisamente el documento original de los registros y, de la misma forma que ocurre con los impresos originales, contiene la forma, dimensión y tamaño de cada una de las casillas (campos) de cada formulario (registro).

El fichero .MYD contiene los datos, es decir todo lo que hay escrito en cada una de las casillas de cada uno de los impresos de ese cajón (tabla) concreto.

No hemos aludido aún a los ficheros con extensión .MYI y son un elemento importante. Contienen los índices, que –como su propio nombre indica– cumplen una función idéntica a los índices de los libros. A través de ellos resulta mucho más rápido encontrar una determinada información y al igual que ocurre con los libros –índice general, onomástico, etcétera– pueden ser varios y con contenidos distintos.

¿Cómo empezar con las bases de datos?

De igual modo que ocurriría en el símil anterior, al instalar MySQL ya creamos el armario archivador –el directorio data– y también dos cajoncitos –las bases de datos mysql y test– pero por pura cuestión de orden vamos a necesitar algún otro armario para poder guardar nuestras cosas.

Lo razonable será empezar creando nuestros armarios (bases de datos) para que posteriormente podamos ir diseñando los documentos –los campos y la estructura– de cada uno de los tipos de impreso (tablas) que vayamos a manejar.

Nuestras bases de datos

Utilizaremos dos bases de datos distintas. Una de ellas –a la que llamaremos ejemplos– contendrá todos los ejemplos que vayamos desarrollando y la otra –practicas– será donde habrás de insertar las tablas que irás elaborando en los ejercicios y en la Actividad Final del Curso.

Los ejemplos aún no están creados y serás tú quien lo vaya haciendo medida que avancemos en esta parte del curso. Lo haremos de forma muy similar a la que hemos visto en páginas anteriores.

Según vayamos desarrollando los contenidos, insertaremos ejemplos de código fuente –de forma similar a la de temas anteriores– y cuando sea necesario crear bases de datos o tablas pondremos un recuadro rojo sobre el que deberás ir pulsando para auto generar los ejemplos.

En tales casos, no olvides hacerlo pues esa será la forma en la que progresivamente vayamos creando elementos necesarios para ser utilizados en los ejemplos posteriores.

Servidores activos

De ahora en adelante, para seguir el Curso vamos a necesitar tener siempre activos tanto el servidor Apache como MySQL. De no hacerlo así, nos aparecerá un mensaje de error diciendo:

Can't connect to MySQL server on 'localhost' (10061)

Si ello te ocurriera, comprueba el semáforo. Probablemente esa será la causa del error.

Organización de la información


Hemos instalado MySQL en el directorio c:\mysql y durante el proceso de instalación se creó un subdirectorio llamado data que es el destinado a albergar todas las bases de datos que vayamos creando.


Como puedes ver en la tabla siguiente, durante la instalación se crearon dos bases de datos llamadas mysql y test.








El directorio MySQL
Las carpetas del subdirectorio data de c:\mysql corresponden a cada una de las bases de datos que contiene Cada una de las tablas que contiene una base de datos tiene tres ficheros con extensiones .frm, MYD y MYI


Los ficheros con extensión .frm contienen la estructura de cada tabla, los MYD los datos y los que tienen extensión .MYI contienen los índices de esa tabla.


En la instalación también se crearon seis tablas en la base de datos mysql. Sus nombres –puedes verlos en la imagen– son: user, db, func, host,
tables_priv y columns_priv.


La tabla user –la más importante para nuestros fines– contiene información sobre los usuarios, desde qué máquinas pueden acceder a nuestro servidor MySQL, sus claves y contraseñas y los permisos de acceso de cada uno de ellos.


Las restantes contienen información sobre las máquinas que pueden acceder al sistema, las bases de datos a las que tendrá acceso cada usuario y las limitaciones o restricciones que eventualmente pudieran establecerse.



El uso de los tres ficheros anteriores, es condición de las tablas tipo MyISAM que es el tipo, por defecto, que utiliza MySQL 4.0. Otros tipos, que veremos en temas posteriores, tales como InnoDB almacenan la información con una estructura diferente.

La tabla user


Activemos nuestro servidor MySQl que, como recordarás, arrancaba pulsando en el icono winmysqladmin.exe situado en c:\mysql\bin y que, como recordarás también, nos colocaba un semáforo verde en la parte derecha de la barra del menú de Windows.


Una vez activo el servidor MySQL ya podemos utilizar phpMyAdmin. Lo habíamos instalado en un subdirectorio de htdocs llamado myadmin. Así que accedamos a través de la dirección: http://localhost/MyAdmin/ y se nos abrirá una página como la que sigue:




PHPmyAdmin

Elegiremos la base de datos mysql

Al seleccionar mysql en el menú de la izquierda y pulsar sobre mysql (en negro en la parte superior de la lista de tablas) aparecerá la lista que está a la derecha de esta imagen.


Allí vemos la tabla user y un enlace activo que dice Examinar. Si pulsamos sobre el podremos ver un contenido similar a este que vemos aquí debajo.





Como ves, hay tres usuarios y dos de ellos como nombre root y ninguna contraseña han sido creados automáticamente durante la instalación. El tercero de ellos –el usuario pepe– es el que hemos creado durante el proceso de instalación


Esta configuración es insegura ya que con los nombres de usuario por defecto –root– y sin contraseña cualquiera podría acceder y manipular las bases de datos.


Más adelante podremos borrar esos usuarios pero, por el momento, dejémoslos así y añadamos un nuevo usuario.


Regresemos al menú anterior y pulsemos en la opción Insertar correspondiente a la tabla user.




Escribamos localhost en el campo Host, jose en el campo User, josefa en el campo Password y marquemos todas las opciones –una lista bastante larga por cierto– como YES (Y) y –muy importante– seleccionemos la función PASSWORD para el campo del mismo nombre.


Una vez realizado el proceso anterior deberá quedarnos como aparece en la imagen. Pulsaremos en el botón Continúe que hay al final de la página y habremos dado de alta al usuario jose con todos los privilegios para gestionar las bases de datos.




Si regresamos de nuevo a Examinar veremos que ya ha sido incluido el nuevo usuario y que el campo contraseña aparece encriptado como consecuencia de haber aplicado la función PASSWORD para garantizar la privacidad del usuario. MySQL requiere esta encriptación.


Respecto a los YES, la explicación es sencilla. Esas opciones permiten habilitar permisos para determinadas operaciones dentro de las bases de datos y lo único que hemos hecho ha sido conceder todas la facultades de gestión al usuario pepe.

Creación de un fichero INCLUDE


En los scripts PHP con los que manejemos las bases de datos vamos a necesitar insertar continuamente: nombre del servidor, nombre de usuario y contraseña.


Tanto la comodidad como la privacidad que hemos mencionado en páginas anteriores aconsejan guardar los datos de usuario en lugar seguro. Así que vamos a crear un fichero –llamémosle mysql.inc.php– idéntico al que tenemos aquí debajo,(podemos copiar y pegar) y guardémoslo en nuestro directorio de seguridad que –como recordarás– estaba en c:\apache\seguridad.

<?
$mysql_server="localhost";
$mysql_login="pepe";
$mysql_pass="pepa";

?>




Fuente:

Manual de PHP 68. PDF. Header´s y visualización

¿Qué es un header?

En un documento PHP se pueden incluir instrucciones que obliguen al navegador del cliente a comportarse de una manera determinada.

Esas instrucciones que dicen al navegador del cliente cómo tiene que comportarse, van contenidas en la header de la página y pueden resultar muy útiles como complemento de otras funciones.

Su nombre se debe a que han de ser –obligatoriamente– lo primero que ha de recibir el navegador en el momento de ser atendida su petición. El grado de exigencia de esta condición es tal que ni siquiera se permite que les preceda ni una línea en blanco.

¿Cómo colocar las cabeceras?

Los header han de colocarse de forma que sus contenidos sean lo primero que aparezca en la página que llega al cliente y eso significa que:

• No puede aparecer delante de un header ninguna etiqueta HTML ni ningún contenido de este tipo.

• Ni siquiera se permite que se les anteponga una línea en blanco.

Requieren muchísima atención y cerciorarse siempre de que la marca del comienzo del script PHP () esté siempre en la primera línea del documento, sin dejar líneas en blanco delante de ella.

Puede que te preguntes: ¿ha de ir también en la primera línea del script PHP?

La respuesta es esta: tienen que ir antes de la primera función que genere una salida hacie el navegador del cliente.

Intentaremos aclarar esta idea.

Los scripts PHP (lo contenido entre y ?>) se ejecutan en el servidor y de ellos sólo llegan al navegador del cliente los resultados de la ejecución (las salidas echo o print, por citar dos ejemplos).

Las cabeceras han de llegar al navegador antes que esas posibles salidas, lo cual no es óbice para que se puedan efectuar –antes de insertar las headers– procesos que no produzcan salidas de tipo print, echo, etcétera.

La sintaxis de algunas header varía en algunos casos –lo podemos ver en el ejemplo– según el protocolo que utilice el servidor. Lo habitual es que lo servidores utilicen uno de estos: HTTP/1.1 ó HTTP/1.0.

Para saber cuál utiliza nuestro servidor basta con visualizar el info.php y buscar la directiva SERVER_PROTOCOL.

Los diferentes haeder

En los ejemplos que aparecen en la columna de ejemplos final están comentadas algunas de las cabeceras que es posible insertar en los ficheros PHP.

Cabría añadir la siguiente:

header("Location:dirección")

Mediante este header se redirecciona el navegador a la URL (absoluta o relativa) que se indicada en el parámetro dirección.

Cuando el navegador recibe un header de este tipo realiza de forma automática la petición de la página indicada en él.

Otra funciones PDF

Existe una función muy útil para un montón de propósitos que PHP empezó a incluir a partir de la versión 4.0.5. Se trata de la función

$b=pdf_get_buffer($p)

Esta función recoge en una variable $b el contenido de un documento PDF -identificado por $p- pudiendo enviarlo al navegador directamente desde la memoria del servidor y que, por tanto, no necesita ser escrito ni almacenado en el servidor.

La utilización de esa función requiere una modificación en la sintaxis -respecto a la de los ejemplos anteriores- y el uso de dos funciones nuevas, que son:

$p=pdf_new()

que es la función que generará un identificador de recurso, distinto de los que hemos venido utilizando hasta ahora, ($p) para el nuevo fichero PDF y que debe insertarse delante de:

pdf_open_file($p)

que abriría un fichero pdf en memoria.

Como observarás esta sintaxis difiere de la que hemos venido utilizando hasta ahora y que era la siguiente:

$f = fopen(nombre, "w");
$g = pdf_open($f)

Con esta sintaxis, creábamos (mediante la función fopen) un documento en el servidor y su identificador de recurso ($f); luego, creabámos un segundo identificador de recurso $g – por medio de pdf_open– que asociábamos con el anterior para que los resultados de las funciones pdf se fueran escri- biendo en el fichero abierto con la primera instrucción.

Ahora no necesitamos crear ningún documento y bastará con un solo identificador de recurso, que es, la salida de la función pdf_new.


Utilización de header


En este ejemplo se utilizan algunas header e incluimos como comentarios las utilidades de cada una de ellas

<?
#esta variable recoge el nombre del fichero a visualizar
$fichero="ejemplo132.pdf";
#esta función determina la longitud en bytes del fichero
$len = filesize($fichero);
/* esta cabecera -válida para HTTP/1.1- ordena al navegador
que no permita guardar la página
que no permita que se almecene en la caché del cliente*/
header("Cache-Control: no-store, no-cache, must-revalidate");
/* esta otra cabecera -válida para HTTP/1.0
indica al navegador que no guarde la página en la caché del cliente
he puesto ambas opciones para cubrir todo el especto probable */
header("Pragma: no-cache");
/* esta cabecera especifica al navegador el contenido
que va a recibir que en este caso no sería otra cosa
que algo que requiere una aplicacion capaz de interpretar
ficheros pdf */
header("Content-type: application/pdf");
/* como la norma de los headers establece que
siempre que se conozca el tamaño del contenido enviado
se incluya en la cabecera ese contenido, pues...
incluimos el tamaño ya que "filesize" nos midió el fichero
y guardo esa medida en la variable $len...
pero... fue posible utilizar esa función antes de las header
porque esa medida no fue mandada a la salida...
si hubiéramos escrito antes de los header... algo así como
Echo $len; ... la habríamos fastidiado...
ya habríamos tenido error en las cabeceras...*/
header("Content-Length: $len");
/* con esta otra header indicamos ls forma de presentación de
el contenido del documento... permite dos posibilidades
inline (la que he puesto aquí) o
attachment (que seria como fichero anexo)
fijate que en este "header" he puesto en filename un nombre distinto
del que tenía el fichero original... eso no tiene importancia
solo será el nombre con el que se guardará en la caché del cliente
en el caso de que no hubiéramos incluido la cabecera "no cache"
que dicho sea de paso... la he puesto aquí como ejemplo
pero que serían absolutamente innecesarias para este ejemplo
de visualización del documento */
header("Content-Disposition: inline; filename=felipe.pdf");
/* ya se acabaron las cabeceras del documento
aquí le decimos al servidor que lea el fichero y lo envie
al navegador del cliente... este ya lo interpretará
siguiendo las especificaciones que le hemos incluido
las cabeceras....*/
readfile($fichero);
?>



Visualización ficheros PDF creados en memoria

<?
# Creamos el PDF con las nuevas funcionesn>
$g = PDF_new();
pdf_open_file($g);
# A partir de aquí todo es igual a los ejemplos anteriores
pdf_begin_page($g, 595, 842);
$imagen1 = pdf_open_jpeg($g, "./images/cruz.jpg");
$h=0.5;
$v=0.8;
pdf_save($g);
$x1 = pdf_get_value($g, "imagewidth", $imagen1);
$y1 = pdf_get_value($g, "imageheight", $imagen1);
pdf_scale($g,$h,$v);
pdf_place_image($g, $imagen1, ((595/$h-$x1)/2), (842/$v-$y1), 1.0);
pdf_close_image ($g,$imagen1);
pdf_restore($g);
pdf_save($g);
$imagen2 = pdf_open_gif($g, "./images/cruz.gif");
$ancho=150;
$alto=325;
$x1 = pdf_get_value($g, "imagewidth", $imagen2);
$y1 = pdf_get_value($g, "imageheight", $imagen2);
$h=$ancho/$x1;
$v=$alto/$y1;
pdf_scale($g,$h,$v);
pdf_place_image($g, $imagen2, ((595/$h-$x1)/2), 200, 1.0);
pdf_close_image ($g,$imagen2);
pdf_restore($g);
PDF_end_page($g);
pdf_close($g);

# Después del pdf_close empezamos la lectura del buffer
$buffer = PDF_get_buffer($g);
/* Esta porción de código es idéntica a la del ejemplo anterior
con la única diferencia que ahora medimos la longitud de la cadena
buffer en vez de la longitud de un fichero como hacíamos allí */
$len = strlen($buffer);
Header("Content-type: application/pdf");
Header("Content-Length: $len");
Header("Content-Disposition: inline; filename=loquesea.pdf")
;
# Escribimos en el documento que se enviará al cliente
# el contenido de la cadena buffer
echo $buffer;
/* liberamos la memoria que contenía el fichero
con lo cual el documento solo aparecerá en el navegador del cliente
y en la caché de este (con el nombre loquesea.pdf).
Si no queremos que se almacene en la caché sería solo cuestión de
incluir las cabeceras no caché del ejemplo anterior */
pdf_delete($g);
?>



Una opción alternativa


En el caso de que no sea posible utilizar las funciones anteriores por incompatibilidad de versiones PHP o de las propias librerías PDF, se puede recurrir a un truco. Se trata de escribir el fichero PDF en servidor, enviarlo al cliente y, posteriormente, borrarlo. Ello serviría, al menos, para economizar espacio de almacenamiento en el servidor.

<?
# creo un fichero de la misma forma que
# lo hacíamos en ejemplo de páginas anteriores
$filename="leocadio.pdf";
$f = fopen($filename, "w");
$g = pdf_open($f);
pdf_begin_page($g, 595, 842);

/* aqui insertaríamos el código
para la generación del pdf.
En este caso lo cerramos en blanco */

PDF_end_page($g);
pdf_close($g);

# cerramos el fichero leocadio.pdf
fclose($f);
/* ahora insertamos exactemente el codigo
del primer ejemplo de esta página.
Fijate que pese a haber escrito un montón de código
aun estamos a tiempo de insertar las funciones de cabecera
ya que NO HE ENVIADO AUN NINGUNA SALIDA AL NAVEGADOR
eso sí, no olvides que delante de <? no puede haber
ninguna linea en blanco...*/
$len = filesize($filename);
header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline; filename=felipe.pdf");
readfile($filename)
;
/* ahora que ya he enviado
el contenido del fichero pdf al navegador
ya puedo borrar el fichero del servidor

unlink($filename);
/* como habrás observado
se trata de una chapuza en tres actos
1º.- Cramos el fichero en el servidor y lo cerramos
2º.- Leemos el contenido del fichero
3º.- Borramos el fichero del servidor */
?>






Fuente: