Introducción a la programación en PHP

PHP

PHP es un lenguaje del lado del servidor más extendido en la web. Nació en 1994, se trata de un lenguaje de creación relativamente reciente, aunque con la rapidez con la que evoluciona Internet parezca que ha existido toda la vida. Es un lenguaje que ha tenido una gran aceptación en la comunidad de desarrolladores, debido a la potencia y simplicidad que lo caracterizan, así como al soporte generalizado en la mayoría de los servidores de hosting. 



PHP nos permite embeber su pequeños fragmentos de código dentro de la página HTML y realizar determinadas acciones de una forma fácil y eficaz, combinando lo que ya sabemos del desarrollo HTML. Es decir, con PHP escribimos scripts dentro del código HTML, con el que se supone que ya estamos familiarizados. Por otra parte, y es aquí donde reside su mayor interés con respecto a los lenguajes pensados para los CGI, PHP ofrece un sinfín de funciones para la explotación de bases de datos de una manera llana, sin complicaciones.

Podríamos efectuar la quizás odiosa comparación de decir que PHP y ASP son lenguajes parecidos en cuanto a potencia y dificultad si bien su sintaxis puede diferir sensiblemente. Algunas diferencias principales pueden, no obstante, mencionarse:
Actualizado: En estos momentos ya no es tan polémica la comparación de PHP con ASP, puesto que son dos lenguajes que han evolucionado de maneras distintas. Mientras que ASP se ha estancado y han salido productos nuevos como .NET para sustituirlo, PHP ha ido mejorando mucho con los años y actualmente su potencia y posibilidades son totalmente distintas, con lo que ha dejado muy atrás la competencia con ASP. Este manual lo comenzamos con la versión 3 de PHP y hoy ya van por la 5 y están cerca de sacar la versión 6. Así pues ya no tiene mucho sentido comparar PHP con ASP, aunque las líneas siguientes a esta nota, que distinguen ASP de PHP, pueden ser de utilidad y una referencia válida, puesto que estas diferencias no han cambiado a día de hoy.

Así mismo, queremos informar que a pesar del manual tener ya cierto tiempo publicado, siempre lo estamos actualizando cuando surgen cambios en los modos de trabajo con PHP.

•    PHP, aunque multiplataforma, ha sido concebido inicialmente para entornos UNIX y es en este sistema operativo donde se pueden aprovechar mejor sus prestaciones. ASP, siendo una tecnología Microsoft, esta orientado hacia sistemas Windows, especialmente NT.

•    Las tareas fundamentales que puede realizar directamente el lenguaje son definidas en PHP como funciones mientras que ASP invoca más frecuentemente los objetos. Por supuesto, esto no es más que una simple cuestión de forma ya que ambos lenguajes soportan igualmente ambos procedimientos.

•    ASP realiza numerosas tareas sirviéndose de componentes (objetos) que deben ser comprados a determinadas empresas especializadas (o programados por nosotros mismos en otros lenguajes). PHP presenta una filosofía totalmente diferente y, con un espíritu más generoso, es progresivamente construido por colaboradores desinteresados que implementan nuevas funciones en nuevas versiones del lenguaje.. 


A CONTINUACION  VEAMOS LO QUE SE PUEDE HACER CON PHP

VARIABLES GLOBALES  DE UN RECORDSET

declarar e inicializar un conjunto de variables globales a partir de una fila de un recordset.

Llegado el caso podría ser interesante que los datos devueltos en una consulta pasen a ser variables globales de PHP para una posterior manipulación más práctica.

Si de ahora en adelante surge la necesidad de realizar esto, no hay más que ejecutar el script siguiente:

function recibe_fila($fila){

 foreach($fila as $nombre_campo => $valor){

   if (gettype($nombre_campo)!="integer"){
    $asignacion = "\$GLOBALS[\"" . $nombre_campo . "\"]=";

    if((is_integer($valor) || (is_float($valor))
     $asignacion.= $valor . ";";
    else $asignación.= "'". $valor. "';";
   eval($asignacion);
   //echo $asignacion . "<br>";
   }

 }

Recibe como parámetro toda la fila devuelta por la consulta. Ya dentro de la función, por cada atributo contenido en la fila, averigua el tipo de cada clave del array (ya que el bucle foreach siempre asigna 2 claves por cada una - una numérica, que es el índice del nombre del campo en la tabla, y la otra alfanumérica, que es el nombre del campo), y, por cada clave alfanumérica, averigua el tipo del valor a asignar a $GLOBALS["atributo"] (si es numérico no va entre comillas, y si es una cadena sí las lleva). Lo último a realizar es pasarle a la función eval() la sentencia de asignación, para así interpretarla como sentencia PHP.

FORMATEO DE UNA CADENA

Script PHP que formatea una cadena a introducir en una base de datos, para asegurarse de que no estropea una sentencia SQL.

 function str_asegurar($cadena){
//elimino etiquetas HTML y PHP
$cadena = strip_tags($cadena);
//elimino el caracter comilla, que puede estropear una sentencia
$cadena = str_replace("'","´",$cadena);

return $cadena;
}

Después de haber ejecutado el script, sólo queda realizar la sentencia de inserción.


RECOMENDAR UN SITIO USANDO PHP 


Este sistema permite al usuario enviar desde la web, un e-mail a otra persona, invitándolo a visitar el sitio.
 
Solo requiere un módulo PHP que se encargará de mostrar el formulario de recomendación, enviar el e-mail y devolver un acuse de envío.

 <!-- formulario de recomendación -->

<? if ($HTTP_GET_VARS["accion"] == "") {
?>

<form method="post" action="recomendar.php?accion=enviar" name="recomienda">
<b>Recomienda este sitio</b><br><br>
Tu Nombre: <input type="text" name="n_remitente" size="10"><br>
Tu E-mail: <input type="text" name="e_remitente" size="20"><br>
Nombre de tu amigo: <input type="text" name="n_destinatario" size="10"><br>
E-mail de tu amigo: <input type="text" name="e_destinatario" size="20"><br><br>
<input type="submit" value="Recomendar">
</form>

<!-- envío del formulario y acuse de envío o información de errores -->
<?
}

elseif ($HTTP_GET_VARS["accion"] == "enviar") {

// recojo las variables que vienen desde el formulario
$n_destinatario = $HTTP_POST_VARS["n_destinatario"];
$e_destinatario = $HTTP_POST_VARS["e_destinatario"];
$n_remitente = $HTTP_POST_VARS["n_remitente"];
$e_remitente = $HTTP_POST_VARS["e_remitente"];

// si los campos no están vacíos
  if ($n_destinatario != "" && $e_destinatario != "" && $n_remitente != "" && $e_remitente != "") {

//indica la url de tu sitio
    $url = "http://www.tusitio.com";
//indica el nombre de tu sitio
     $nombre_del_sitio = "Tu Sitio";
//indica el asunto del mensaje
     $asunto = $n_remitente . " te recomienda un sitio";
//redacta el mensaje
     $mensaje = "Hola " . $n_destinatario . ":<br>";
     $mensaje .= $n_remitente . " te recomienda que visites <b>" . $nombre_del_sitio . "</b>.<br>";
     $mensaje .= "Puedes verlo en <a href='" . $url . "'>" . $url . "</a><br><br>Saludos!";

//indica que el mail se envía en formato HTML

     $encabezado = "From:".$e_remitente."\nReply-To:".$e_remitente."\n";
     $encabezado .= "X-Mailer:PHP/".phpversion()."\n";
     $encabezado .= "Mime-Version: 1.0\n";
     $encabezado .= "Content-Type: text/html";

//envía el mensaje

     mail($e_destinatario,$asunto,$mensaje,$encabezado);

//Informa al usuario que se ha enviado el mensaje

     echo "<b>El mensaje ha sido enviado</b>.<br>Gracias por recomendarnos!";

     }

//si existen campos vacíos, envía un mensaje de error

     else {

     echo "Por favor, es necesario que completes todos los campos.<br>";
     echo "<a href='recomendar.php'>Pincha aquí</a> para corregir los campos.";

     }

}
?>

 RECOGER DATOS DE UN SELECT MULTIPLE CON PHP

Quizá un problema que se nos puede plantear durante el trabajo con PHP, es querer recoger los datos de un Select Múltiple. Recordamos que un select múltiple es un campo de formulario donde se pueden seleccionar varios elementos a la vez.

Nota: Para seleccionar varios elementos de un campo select múltiple, tenemos que utilizar el botón de "control" e ir pulsando cada uno de los elementos que deseamos seleccionar. Es importante que este punto quede claro para los visitantes de vuestras páginas, ya que es muy habitual que los usuarios no sepan manejar este tipo de campos.

<form action="trataformulario.php" method="POST"> 
Nombre: <input type="text" name="nombre"><br> 
Apellidos: <input type="text" name="apellidos"><br> 
Email: <input type="text" name="email"> <br> 
Cerveza: <br> 
<select multiple name="cerveza">  
<option value="SanMiguel">San Miguel</option>  
<option value="Mahou">Mahou</option>  
<option value="Heineken">Heineken</option>  
<option value="Carlsberg">Carlsberg</option>  
<option value="Aguila">Aguila</option> 
... 
</select><br> 
<input type="submit" value="Enviar datos!" >
</form>


Tenemos este formulario en nuestra página y queremos recoger los datos introducidos por el usuario. Para los campos "nombre", "apellidos" y "email" no tenemos ningún tipo de problema, recogemos los datos por el método habitual, es decir:

<?php
echo "Nombre: ". $_POST["nombre"];
echo "<br>Apellidos: ". $_POST["apellidos"];
echo "<br>E-mail: ". $_POST ["email"];
?>

Uno se podría preguntar, y porque no puedo poner "$cerveza=$_POST["cerveza"]"? el problema reside en que los option del select múltiple tienen todos el mismo nombre y en caso de tener varios elementos seleccionados sólo obtendríamos el último elementoº. Y como resolver esto? Pues bien, la solución es bien sencilla. Basta con poner en el final del nombre del campo del select múltiple unos corchetes ([]), en nuestro caso sería "cerveza[]". De este modo PHP interpreta el campo en cuestión como un array con tantas posiciones como elementos haya seleccionados en el select múltiple. Veamos pues como quedaría nuestro ejemplo... 
 
<form action="trataformulario.php" method="POST"> 
Nombre: <input type="text" name="nombre"><br> 
Apellidos: <input type="text" name="apellidos"><br> 
Email: <input type="text" name="email"> <br> 
Cerveza: <br> 
<select multiple name="cerveza[]">  
<option value="SanMiguel">San Miguel</option>  
<option value="Mahou">Mahou</option>  
<option value="Heineken">Heineken</option>  
<option value="Carlsberg">Carlsberg</option>  
<option value="Aguila">Aguila</option> 
... 
</select><br> 
<input type="submit" value="Enviar datos!" >
</form> 


Y para recoger la información y tratarla actuaríamos del siguiente modo.. 

 <?php
echo "Nombre: ". $_POST["nombre"];
echo "<br>Apellidos: ". $_POST["apellidos"];
echo "<br>E-mail: ". $_POST ["email"];
$cervezas=$_POST["cerveza"];

//recorremos el array de cervezas seleccionadas. No olvidarse q la primera posición de un array es la 0

for ($i=0;$i<count($cervezas);$i++)  
{   
echo "<br> Cerveza " . $i . ": " . $cervezas[$i];  
}
?>


 Nota: Al ponerle este tipo de nombres (terminando en corchete) a un campo de un formulario y si usamos funciones Javascript para validarlos, manejarlos, etc... debemos añadir a dicho campo, además del nombre, el atributo de HTML id y utilizar este último como identificador del campo, en vez del nombre que se haya colocado en el atributo name, puesto que daría problemas.
 El código completo de este ejemplo podría ser el siguiente. Sería bueno fijarse que hemos colocado todo el código en un archivo PHP. Ese código tiene un formulario reentrante, es decir, la página se llama a si misma para procesar el formulario

<?
if (!$_POST){
?>
<form action="select_multiple.php" method="POST">
    Nombre: <input type="text" name="nombre"><br>
    Apellidos: <input type="text" name="apellidos"><br>
    Email: <input type="text" name="email"> <br>
    Cerveza: <br>
    <select multiple name="cerveza[]">
       <option value="SanMiguel">San Miguel</option>
       <option value="Mahou">Mahou</option>
       <option value="Heineken">Heineken</option>
       <option value="Carlsberg">Carlsberg</option>
       <option value="Aguila">Aguila</option>
    </select><br>
    <input type="submit" value="Enviar datos!" >
</form>
<?
}else{

    echo "Nombre: ". $_POST["nombre"];
    echo "<br>Apellidos: ". $_POST["apellidos"];
    echo "<br>E-mail: ". $_POST ["email"];
    $cervezas=$_POST["cerveza"];

    //recorremos el array de cervezas seleccionadas. No olvidarse q la primera posición de un array es la 0

    for ($i=0;$i<count($cervezas);$i++)
       {
       echo "<br> Cerveza " . $i . ": " . $cervezas[$i];
       }

   }
?>  


PAGINACION CON PHP Y SyBASE

 <?php
$conn = sybase_connect("labsededatos", "elsuario", "");

$TAMANO_PAGINA = 20;

$pagina = $_GET["pagina"];
if (!$pagina) {
    $inicio = 0;
    $pagina=1;
}
else {
    $inicio = ($pagina - 1) * $TAMANO_PAGINA;
}
//Importante hace el query ordenado y sin limit
$ssql = "select * from data_user ORDER by nombre";
$rs = sybase_query($ssql,$conn);
$num_total_registros = sybase_num_rows($rs);

$total_paginas = ceil($num_total_registros / $TAMANO_PAGINA);

echo "Número de registros encontrados: " . $num_total_registros . "<br>";
echo "Se muestran páginas de " . $TAMANO_PAGINA . " registros cada una<br>";
echo "Mostrando la página " . $pagina . " de " . $total_paginas . "<p>";

$rs = sybase_query($ssql,$conn);

$arreglo[] ="";
while ($fila = sybase_fetch_object($rs)){
    $arreglo[]="$fila->nombre";
}

sybase_free_result($rs);
sybase_close($conn);

$contarray=1;

//Aqui, paso los datos extraidos en el query a un arreglo
//si son más campos como nombre, apellido...
//se puede trampiar así: $arreglo[]="$fila->nombre, $fila->numero_tlf";

foreach ($arreglo as $idarray=> $nombre){
    //aqui se hace la verifiación que funciona como el limit

    if ($idarray > $inicio && $contarray <= $TAMANO_PAGINA){
       echo "$idarray $nombre<br>";
       $contarray++;
    }
}
if ($total_paginas > 1){
    for ($i=1;$i<=$total_paginas;$i++){
       if ($pagina == $i){
          echo $pagina . " ";
       }else{
          echo "<a href='dbd2.php?pagina=" . $i . "'>" . $i . "</a> ";
       }
    }
}

?> 

CREACION DE UN LOG DE ERRORES 

Como crear un archivo que almacena los errores que se han producido durante la ejecución de un programa, añadir un log de errores a nuestra página.


Un log de errores, nos permitirá controlar cuando se ha producido un error para corregirlo y evitar que se repita en el futuro.

Para crear un log, abriremos el archivo en modo 'a' (escritura al final) y escribiremos el error indicando la fecha, para simplificar el trabajo lo podemos incluir todo en una función: 

<?php
function error($numero,$texto){
$ddf = fopen('error.log','a');
fwrite($ddf,"[".date("r")."] Error $numero: $texto\r\n");
fclose($ddf);
}
?>


Una vez declarada la función, tansolo tendremos que llamarla de la siguiente manera cuando se produzca un error para que se guarde en error.log:

<?php
// Si no existe la cookie sesion
if(!isset($_COOKIE['sesion'])){
// Guardamos un error
error('001','No existe la cookie de sesion');
}
?>


De esta manera, cada vez que un usuario entra a esta página sin la cookie sesion, se almacena una nueva línea en el fichero indicando:

[fecha] Error 001: No existe la cookie de sesion

Vamos a ver ahora como podemos mejorar esto de manera que ademas de poder grabar los errores que nosotros definamos en nuestro sitio, nos almacene los errores producidos durante la ejecución del script php.

Esto lo conseguiremos indicando al interprete Zend que llame a la
función error() cada vez que el código PHP contenga un error con la
función set_error_handler:

<?php
set_error_handler('error');
?>


Entonces, el código completo nos queda de la siguiente manera:

<?php
function error($numero,$texto){
$ddf = fopen('error.log','a');
fwrite($ddf,"[".date("r")."] Error $numero:$texto\r\n");
fclose($ddf);
}
set_error_handler('error');
?> 


Y de esta manera damos por finalizado nuestro script para generar un
log de errores personales y de PHP.


RECUPERAR LA CALIDAD DE UNA IMAGEN JPEG

una función que permite regenerar prácticamente una imagen con su color real, una de las principales deficiencias cuando usamos sistemas de Thumbnail.

Esta función es: imagecreatetruecolor($ancho, $alto); El resto del proceso ya lo conocemos.

header("Content-type: image/jpeg");
$src_img= @imagecreatefromjpeg(‘LA IMAGEN.JPG’)
$dst_img = @imagecreatetruecolor($ANCHO,$ALTO);


@imagecopyresized($dst_img, $src_img, 0,0,0,0, $ANCHO, $ALTO, ImageSX($src_img), ImageSY($src_img)); 

@imagejpeg($dst_img);
@imagedestroy($dst_img); 


Explicación:  En primer lugar enviamos una cabecera pura con el tipo de documento:
 header();

Guardamos en la variable $src_img una nueva imagen creada de tipo JPEG apartir de LA IMAGEN.JPG que será la imagen que redimensionaremos o la editaremos.

Luego en la variable $dest_img, Creamos una imagen nueva con color REAL, esta será la que utilizaremos para mostrarla, nótese que no esta definidas las variables $ANCHO, $ALTO. Estas variables guardan el nuevo tamaño de la imagen que obviamente sera inferior a la original, por lo cual pueden ayudarse con la función getsizeimage(); que bueno devuelve un vector con los píxeles de X y Y , o en su efecto ImageSX() y ImageSY() para obtener en base a esos parámetros el nuevo tamaño uniforme y acorde con nuestra galería de imágenes.

Imagecopyresized(), bueno el nombre lo dice, copia solo partes de una imagen REDIMENSIONADA .

Luego mostramos la imagen con imagejpeg(); si queremos que se guarde en el directorio con sus respectivos permisos, agregaremos un nuevo parámetro:


@imagejpeg($dst_img,'NUEVAIMAGEN.JPG');

Destruimos la imagen para ahorrar memoria utilizada por imagecreatefromjpeg() y los procesos subsiguientes;

Y bueno, como ya sabemos, la @ (arroba) al comienzo de cada función sirve para evitar que se imprima el error en pantalla. Si es de su preferencia pueden quitarlas.


COMPRIMIR PAGINA PHP

Para aligerar el tiempo de carga de nuestras páginas generadas con PHP, podemos enviarlas al navegador comprimidas con GZip utilizando las funciones de control de salida, para ello, llamaremos a la funcion predefinida ob_gzhandler cómo tratante de la funcion ob_start, veamos un ejemplo:

<?
ob_start("ob_gzhandler");

// Contenido de la página, puede contener
// tanto HTML cómo PHP

ob_end_flush();
?>

Tener en cuenta que todo el contenido debe estar en el lugar indicado por lo que los primeros carácteres del documento deben ser <? y los dos últimos ?> y no se debe añadir nada excepto donde se indica, si no vamos con cuidado recibiremos un error parecido al siguiente:

Warning: Cannot add header information...

Otra forma más completa todavía de compresion, consiste en aplicar la misma funcion, pero eliminando a su vez los espacios y saltos de linea de la fuente del documento, lo que no tendra ningun efecto visual pero disminuira el tiempo de descarga, veamos cómo hacerlo:

<?
ob_start();

// Contenido de la página, puede contener
// tanto HTML cómo PHP

$cntACmp =ob_get_contents();
ob_end_clean();
$cntACmp=str_replace("\n",' ',$cntACmp);
$cntACmp=ereg_replace('[[:space:]]+',' ',$cntACmp);
ob_start("ob_gzhandler");
echo $cntACmp;
ob_end_flush();
?>


Este método funciona igual que el anterior solo que antes de comprimir elimina los saltos de linea y espacios innecesarios, pero debemos tener en cuenta las mismas precauciones o no funcionará.

Este método de compresion lo he desarrollado para ProgramacionWeb, como podreis comprovar al ver el código fuente de esta misma página, todo el código aparece sin saltos de linea ni tabulado por una simple cuestion de compresion.

FUNCION DE ESCRIBE UN CAMPO SELECT CON  VALORES DE UNA BASE DE DATOS

Durante el trabajo con formularios en PHP, en muchas ocasiones tenemos un campo select cuyos valores posibles se obtienen de una base de datos, por ejemplo, los países. En este taller vamos a mostrar una función que es capaz de escribir en un formulario un campo de select, obteniendo los valores de una tabla de la base de datos. Con esta función podemos olvidarnos de la complejidad de mostrar un campo select. Simplemente llamamos a la función, enviando los parámetros, y se encarga de mostrar el campo.

 En el caso de los países, puede que sea una buena idea tener una tabla con la lista de países del mundo. En el formulario lo habitual es permitir escoger un país de la lista y enviar el código del país. De modo podemos estar seguros de que todos los usuarios han elegido un país de la lista, entre todos los posibles.

La tabla de países podría contener algo como esto:

 id_pais    nombre_pais
1               España
2               México
3               Argentina
4               Colombia
5               Chile

Este es el código HTML de un posible formulario cuyo campo de países ha sido extraído de la anterior tabla:

 <form>
Nombre: <input type=text name="nombre">
<br>
País:
<select name=id_pais>
   <option value=1>España
   <option value=2>México
   <option value=3>Argentina
   <option value=4>Colombia
   <option value=5>Chile ...
</select>

Función saca_menu_desplegable() 
Ahora vamos a ver cómo se haría la función que recorre la tabla de la base de datos para mostrar el select del país. Para empezar vamos a ver una lista de los parámetros que acepta. 

ssql: sentencia SQL que permita extraer los datos de las posibles opciones del select. La sentencia SQL tendría una forma como esta "select id_pais, nombre_pais from pais". En la primera columna de los registros seleccionados con esta sentencia, se espera el value de los option (en este caso id_pais). En la segunda columna se espera el texto de los option.
valor: En este parámetro se recibe el valor predeterminado que debe aparecer en el select. Este valor se compara con el primer campo de la sentencia SQL. (Si deseamos que el valor predeterminado fuera "España", deberíamos poner un 1 como valor)
nombre: Es el nombre que se le da al campo select de formulario

El código de la función es el siguiente:

 function saca_menu_desplegable($ssql,$valor,$nombre){
   echo "<select name='$nombre'>";
   $resultado=mysql_query($ssql);
   while ($fila=mysql_fetch_row($resultado)){
     if ($fila[0]==$valor){
       echo "<option selected value='$fila[0]'>$fila[1]";
     }
     else{
       echo "<option value='$fila[0]'>$fila[1]";
     }
  }
   echo "</select>";


 Se escribe el campo de formulario select, indicando el nombre del campo que se ha recibido por parámetro. Luego se realiza una búsqueda en la base de datos, ejecutando la sentencia SQL recibida por parámetro.

Más tarde se hace un recorrido del conjunto de registros que se han encontrado en la base de datos y se escriben cada uno de los option. Para cada uno de los registros se comprueba si su identificador es igual al que se desea marcar como valor predeterminado. En caso de serlo, se escribe el option con el atributo selected.

Un detalle importante es que la función necesita tener una conexión abierta con la base de datos, pues en caso contrario no se podría ejecutar la sentencia SQL.