Introducción a PHP 4

 

Noviembre 2000

 

Vicente Aguilar <vaguilar@linuxfreak.com>

 

 

1. Introducción

Aunque PHP y ASP tienen básicamente la misma funcionalidad, su sintaxis es completamente distinta y su semántica también presenta diferencias, por lo que aunque lo que podamos hacer con ASP también lo podamos hacer en PHP (y viceversa), la adaptación de uno a otro lenguaje puede resultar algo complicada al principio.

 

ASP (“Active Server Pages”) es, más que un lenguaje de programación en sí, una tecnología que permite insertar en una página HTML código que se ejecutará en el servidor. Este código puede ser Java, JavaScript o, más comúnmente, VBScript. Por lo tanto cuando en este curso hagamos referencia al “lenguaje ASP”, y no a la tecnología, nos referiremos a VBScript.

 

Por su parte, PHP ("PHP: Hypertext Preprocessor") provee de una tecnología similar a ASP para insertar código en las páginas HTML, pero PHP además de la tecnología es el lenguaje. En PHP sólo podemos incluir código en un lenguaje, PHP, que será el lenguaje que vamos a estudiar en el presente curso.

 

PHP es un lenguaje interpretado basado principalmente en C, C++ y Java, con los que comparte prácticamente toda su sintaxis y semántica, y aporta también algunas características de lenguajes interpretados como Perl y Bash. Debido a esto, una de sus principales características y una gran baza a su favor es que la curva de aprendizaje para programadores que ya conozcan estos lenguajes es muy suave, prácticamente pueden sentarse delante del ordenador y comenzar a escribir código.

 

En cuanto a la tecnología detrás de PHP, ya en la versión 3.0 el intérprete de PHP era bastante más rápido que los intérpretes existentes de ASP, lo que junto con su buena integración con el servidor HTTP Apache y su capacidad de acceder a unos 20 sistemas de Bases de Datos distintos, lo ha convertido en un fuerte competidor frente a las “soluciones” de Microsoft. Con la versión 4.0 de PHP que ha visto la luz hace pocos meses la situación ha mejorado todavía más: el intérprete es más rápido (hasta 12 veces más rápido que el de la versión 3.0); se ha perfeccionado la integración de PHP con otros servidores además de Apache, entre otros IIS; y se ha modularizado todo el diseño interno, entre otras cosas independizado el intérprete del lenguaje PHP (Zend) del módulo de comunicación con el servidor, con lo que a partir de ahora es posible utilizar PHP como lenguaje interpretado en cualquier otro proyecto (ya se está trabajando para utilizar PHP como lenguaje para procedimientos en MySQL.)

 

El presente curso está estructurado en dos secciones: En la primera se introduce la sintaxis y semántica básica de PHP, haciendo especial hincapié en sus diferencias con ASP; En la segunda parte veremos más a fondo algunas de las características de PHP con las que tendremos que trabajar. Por último, enumeraremos algunas características más de PHP que nos hemos dejado en el tintero.


2. El lenguaje PHP

PHP es bastante diferente en su sintaxis a ASP. ASP está basado en VBScript, mientras que PHP toma bastantes características de lenguajes como C, C++ y Java, y algunas también de Perl.

 

A continuación analizaremos en detalle estas diferencias al tiempo que vamos introduciendo las bases de la programación en PHP.

 

2.1. Extensión de los ficheros

La primera diferencia entre ASP y PHP viene a la hora de dar nombre a los ficheros. La extensión es importante ya que el servidor HTTP (en nuestro caso, generalmente Apache) decide si debe pasárselo al procesador de PHP o no en función de esta extensión.

 

Las extensiones que indican al servidor HTTP que el fichero contiene código PHP que debe ser procesado son:

 

 

Aunque haya extensiones diferentes para PHP 3 y 4, no tienen efecto en el intérprete que las procesará IGUAL. En general, PHP 4 es compatible con 3, salvo unas pocas excepciones. Este curso se centra en PHP 4, así que no analizaremos estos casos de incompatibilidad con las versiones anteriores.

 

2.2. Delimitadores

El código ASP se delimita dentro del HTML entre los signos '<%' y %>'. Por ejemplo:

 

<%@ Language=VBScript %>

<html>

<body>

<%IF Hour(time)>20 OR Hour(time)<4 THEN%>

Buenas noches.

<%ELSE%>

Buenos días.

<%END IF%>

</body>

</html>

 

En PHP disponemos de cuatro opciones para delimitar el código:

 

<? echo 'Primer método de delimitar código PHP'; ?>

 

<?php echo 'Segundo método, el más usado'; ?>

 

<script language="php">

echo 'Algunos editores (como el FrontPage) Sólo entienden este método';

</script>

 

<% echo 'Método de compatibilidad con ASP'; %>

 

Los métodos primero y cuarto no siempre estarán disponibles, ya que se pueden activar o desactivar al compilar el intérprete de PHP. En general, preferiremos usar el segundo método.

 

El ejemplo anteriormente expuesto en ASP podría traducirse así a PHP:

 

<html>

<body>

<?php if ( Hour(time)>20 || Hour(time)<4) { ?>

Buenas noches.

<?php } else { ?>

Buenos días.

<?php }?>

</body>

</html>

 

O también así, utilizando la función echo para imprimir cadenas de texto:

 

<html>

<body>

<?php

if ( Hour(time)>20 || Hour(time)<4) {

    echo “Buenas noches.”;

} else {

    echo “Buenos días.”;

}

?>

</body>

</html>

 

Además, se puede imprimir de forma rápida con <%=$var%>, al igual que en ASP.

 

2.3. Fin de línea

En ASP el carácter de fin de línea representa el final de un comando, llamada a una subrutina, etc. En cambio PHP ignora cualquier carácter de espaciado presente en el código, incluyendo espacios, tabuladores y saltos de línea (salvo si se encuentran dentro de una cadena de texto). El fin de sentencia se marca con un carácter de punto y coma.

 

Por ejemplo, los dos trozos de código siguientes son equivalentes:

 

print( date("M d, Y H:i:s", time()) );

 

print (

        date( "M d, Y H:i:s",

               time()

            )

      )

;

 

2.4. Comentarios

En PHP hay tres formas de introducir comentarios en el código, frente al ' de ASP:

 

/* Comentarios estilo C.

 * Pueden extenderse durante varias líneas.

 */

 

// Comentarios estilo C++. Cubren hasta el final de la línea.

 

# Comentarios estilo Bash/Perl. Cubren hasta el fin de línea.

 

Hay que hacer notar que los comentarios de una línea cubren hasta final de línea O HASTA EL FIN DEL BLOQUE PHP ('?>' o el que corresponda.)

 

2.5. Variables

Las variables son una parte fundamental de todo lenguaje de programación. En ellas se almacenan valores con los que se puede operar, se pueden comparar entre sí y se puede hacer variar el flujo del programa en función de su valor. Vamos a ver cómo trabajar con variables en PHP.

 

2.5.1. Declaración y uso

Al contrario que en la mayoría de lenguajes de programación, y al igual que en ASP, en PHP NO hace falta declarar las variables antes de usarlas: tras la primera aparición en el código quedan declaradas. Como diferencia frente a ASP, en PHP todas las variables llevan delante el signo del dólar ‘$’. Ej. :

 

$var_1 = 123;

$var_2 = ’hola’;

$var_3 = $var_1 * 2;

 

2.5.2. Tipado de variables

 

Las variables en PHP están débilmente tipadas, de forma similar a ASP (el tipo mixto Variant de ASP es similar al mixed de PHP.) Una variable se asocia a un contenido, del tipo que sea, estando el tipo indicado en el contenido, no en la variable en sí. Visto de otra forma, una misma variable se puede reutilizar asignándole a lo largo del tiempo datos de distinto tipo. Por ejemplo:

 

$mi_variable = ’Inicializamos como una cadena de texto’;

$mi_variable = 3;                   // Ahora es un entero.

$mi_variable = 3.14 * $mi_variable; // Ahora un float.

$mi_variable = new MiClase();       // Ahora un objeto.

 

A pesar de esto, el tipo es importante en algunos casos (para efectuar operaciones o llamadas a funciones.) En estos casos, PHP se encarga de realizar las transformaciones necesarias de forma automática.

 

$mivar = 123;

echo $mivar;

 

En el ejemplo anterior, PHP convierte el valor entero 123 a la cadena de texto “123” antes de pasárselo a la función echo.

 

$mivar = ’3’;

$mivar = 2 + $mivar;

 

En este caso $mivar comienza almacenando la cadena “3”. En la segunda línea, y para realizar la suma, se convierte al entero 3, se realiza la suma y se asigna a $mivar el entero 5.

 

También se puede forzar la conversión a un tipo específico, por ejemplo:

 

$mivar = (string)123;

 

Y se puede cambiar el tipo de una variable con:

 

$mivar = 12;

settype($mivar, "double");

 

2.5.3. Ámbito

El ámbito de una variable hace referencia a dónde está disponible esa variable y dónde no, y depende del contexto en el que haya sido definida la variable:

 

 

Aunque todos estos conceptos (includes, funciones, clases) los presentaremos más tarde, introduciremos ya una posible fuente de errores: Los programadores acostumbrados a C deben llevar cuidado con las variables globales, ya que no se comportan como en C. Por ejemplo, considérese el código siguiente:

 

$mivar = 3;

function mifuncion() {

   echo $mivar;

}

 

En C, la función mifuncion() imprimiría '3'. En cambio en PHP no imprimiría nada (si no da un error) ya que la variable $mivar de mifuncion es una variable DISTINTA a la global y local a esta función.

 

Para acceder a las variables globales desde una función, hay que utilizar la palabra reservada global:

 

$mivar = 3;

function mifuncion() {

   global $mivar;

   echo $mivar;

}

 

2.5.4. Referencias

En PHP se puede definir “alias” para las variables, es decir, tener dos (o más) nombres distintos para un mismo dato. Se puede ver de forma similar a tener dos punteros en C haciendo referencia a la misma zona de memoria.

 

Para definir una referencia utilizamos el carácter ‘&’ delante de la variable referenciada:

 

$alias = &$variable

 

Así podremos acceder al mismo dato por $alias o $variable. Las modificaciones hechas sobre una u otra repercuten en el mismo dato. Debe quedar claro que la referencia no significa que $alias “apunta a” $variable, si no que tanto $alias como $variable “apuntan a” un mismo contenido en memoria.

 

Se puede eliminar una referencia con la función unset():

 

$a = 1;

$b = &$a;

unset ($a); // Pero $b sigue valiendo 1

 

Las referencias también se pueden usar para pasar o devolver parámetros por referencia en las funciones, como se verá más tarde.

 

2.5.5. Acceso indirecto

En PHP podemos acceder al contenido de una variable cuyo nombre tenemos almacenado en otra variable, de esta forma:

 

$a = 123;

$b = ‘a’;

echo $$b; // 123

 

2.6. Tipos de datos

PHP soporta los siguientes tipos de datos básicos:

 

2.6.1. Enteros (int, integer)

Números enteros en notación decimal, octal (un 0 inicial indica que el valor está representado en octal) o hexadecimal (un 0x indica que es hexadecimal.)

 

Ejemplos:

 

$var1 = 1234; // Número en decimal

$var2 = -1234; // El mismo número, negativo

$var3 = 0123; // El 83 decimal, expresado en octal

$var4 = 0x12; // Valor hexadecimal del 18

 

El tamaño, representación interna y valores máximos dependen  de la plataforma, aunque lo normal son 32 bits con signo (+- 2 billones.)

 

2.6.2. Números en punto flotante (float, double, real)

Los números en punto flotante admiten decimales y su rango de valores es mayor que el de los enteros, a costa de cierta pérdida de precisión en los dígitos menos significativos del número. Se permiten las dos notaciones típicas:

 

$var1 = 1.234; // Número con decimales

$var2 = 1.2e3; // Notación científica, 1.2 * 10^3

 

Internamente se representan mediante 64 bits en formato IEEE (hasta 1.8e308 con una precisión de 14 dígitos decimales.)

 

2.6.3. Arrays (array)

Los arrays representan vectores unidimensionales o multidimensionales. Se definen y acceden como en C,  mediante el nombre de la variable que los contiene e indicando el índice (que comienza en el 0) entre corchetes, en lugar de paréntesis como en ASP. Los elementos de un mismo array pueden ser de tipos distintos, p. Ej. :

 

$MiArray[0] = 1;

$MiArray[1] = “hola!!”;

$MiArray[2] = 5;

 

echo $MiArray[1];

 

Como se ve en el ejemplo, no hace falta definir la dimensión del array antes de usarlo (Dim en ASP), ni, por lo tanto, tampoco redimensionarlo a la hora de añadir más elementos (ReDim.)

 

Si al definir un array omitimos el índice (pero NO los corchetes, ¡estaríamos sobrescribiendo la variable!), el elemento se asigna a la siguiente posición del array sin definir. Siguiendo con el ejemplo anterior:

 

$MiArray[] = 8 // $MiArray[3] = 8

 

Los arrays de PHP admiten también cadenas como índices, de forma simultánea a los enteros. Un mismo array puede funcionar a la vez de forma indexada (como un vector) o de forma asociativa (como una tabla hash):

 

$MiArray[“nombre”] = “Homer”;

 

echo $MiArray[3]; // 8

echo $MiArray[“nombre”]; // Homer

 

Para definir un array multidimensional, simplemente indicamos más índices:

 

$MiOtroArray[1][2][“pepe”][0] = “4 dimensiones!!!”;

 

También podemos definir arrays utilizando los constructores del lenguaje array() o list(), así:

 

$OtroArrayMas = array( 1, “hola”, 5);

 

Donde los valores se asignan por orden a los índices 0, 1 y 2, o de esta otra forma, donde indicamos explícitamente el índice:

 

$YOtroArray = array(

    0 => 1,

    1 => “hola”,

    2 => 5,

    3 => 8,

    “nombre” => “Homer”

);

 

Se pueden definir arrays multidimensionales mediante composición de varias llamadas anidadas al constructor array().

 

2.6.4. Cadenas de texto (string)

Las cadenas en PHP se pueden definir de tres formas:

 

 

Secuencia

Significado

\n

Nueva línea (LF ó 0x0A en ASCII)

\r

Retorno de carro (CR ó 0x0D en ASCII)

\t

Tabulación horizontal (HT ó 0x09 en ASCII)

\\

Barra invertida

\$

Símbolo del dólar

\"

Dobles comillas

\[0-7]{1,3}

Un carácter determinado en notación octal

\x[0-9A-Fa-f]{1,2}

El carácter indicado en hexadecimal

 

 

 

$cadena = <<<DELIMITADOR

texto

texto

texto

...

texto

DELIMITADOR

 

Después del operador “<<<” especificamos un delimitador que marcará el final del texto. Debemos llevar cuidado al elegir este delimitador, ya si aparece en algún lugar del texto, podríamos acabar con un resultado incorrecto. Tras la línea con el “<<<” y el delimitador, escribimos la cadena de texto, que puede expandirse por tantas líneas como queramos. Las variables dentro del texto se expanden y no hace falta escapar las comillas. Para finalizar la cadena, debe aparecer una línea que contenga únicamente el delimitador. Por ejemplo:

 

$cadena = <<<FINCAD

Esto es un ejemplo de cadena como “here doc”.

La variable \$a vale $a.

Ahora vamos a finalizar la cadena:

FINCAD

 

Para concatenar cadenas se utiliza el operador ‘.’ :

 

$cad = ‘A esta cadena ‘;

$cad = $cad . ‘le vamos a añadir más texto.’;

 

Se puede acceder a cada carácter de la cadena de forma independiente utilizando notación de arrays indexados sobre la cadena:

 

$cad2 = “El tercer carácter de \$cad es ‘$cad[2]’.”;

 

Por último, señalar que aunque como ya hemos dicho en una cadena delimitada por dobles comillas se expanden las variables, con construcciones complejas (arrays multidimensionales, objetos...) la expansión NO siempre funciona bien. Para evitar problemas, podemos concatenar la cadena con el valor de la variable o encerrar la variable entre llaves:

 

echo “Esto no irá bien $a[1][3]”;

echo “Así no hay problemas {$a[1][3]}”;

echo ‘Concatenar es otra alternativa ‘ . $cosa->valor;

 

2.6.5. Objetos (object)

Pese a no ser un Lenguaje Orientado a Objetos puro, PHP soporta clases y objetos, aunque con ciertas carencias respecto a otros lenguajes. Las clases y objetos en PHP se definen y usan de forma similar a C++ o Java. Se estudiarán con profundidad en la segunda parte de este curso.

 

2.7. Constantes

En PHP podemos definir constantes utilizando la función define(), cuya declaración es:

 

int define(string nombre, mixed valor [, int noMayusculas])

 

Donde nombre es el nombre que le queremos dar a la constante, valor su valor, y el campo opcional noMayusculas indica si está a 1 que podemos acceder a la variable independientemente con mayúsculas o minúsculas, mientras que si está a 0 (valor por defecto) sólo podremos acceder a ella de la misma forma como la hayamos definido.

 

Las constantes en PHP se diferencian de las variables en que:

 

Un ejemplo de declaración y uso de constantes en PHP sería:

 

define(‘SALUDO’, ‘Hola, mundo!’);

echo ‘La constante SALUDO vale ‘ . SALUDO;

 

2.8. Mayúsculas y minúsculas

Esta puede ser una causa de problemas. En ASP no importa si una función o variable está escrita en mayúsculas o minúsculas, siempre se interpretará igual. En cambio en PHP tenemos un comportamiento mixto:

 

 

Para evitar errores y confusiones, siempre escribiremos los nombres de funciones del sistema en minúscula, y las funciones propias siempre tal y como se escribieran en la declaración.

 

2.9. Operadores

Vamos a ver los distintos operadores disponibles en PHP, clasificados por tipos:

2.9.1. Operadores aritméticos

Disponemos de los clásicos operadores aritméticos:

 

Operación

Nombre

Resultado

$a + $b

Suma

Suma de $a y $b.

$a - $b

Resta

Diferencia entre $a y $b.

$a * $b

Multiplicación

Producto de $a y $b.

$a / $b

División

Cociente de $a y $b.

$a % $b

Módulo

Resto de la operación $a / $b.

 

2.9.2. Auto-incremento y auto-decremento

PHP también dispone de los típicos operadores de auto-incremento y decremento de C:

 

Operación

Nombre

Resultado

++$a

Pre-incremento

Incrementa $a en 1, y devuelve $a (ya incrementado)

$a++

Post-incremento

Devuelve $a (sin incrementar), y después lo incrementa en 1.

--$a

Pre-decremento

Decrementa $a en 1, y después lo devuelve.

$a--

Post-decremento

Devuelve $a, y después lo incrementa en 1.

 

Por si alguien no está familiarizado con el funcionamiento de estos operadores, he aquí un ejemplo para clarificarlo:

 

$a = 1;

$b = $a++; // $b = $a; $a = $a + 1; -> $b vale 1, $a 2.

 

$a = 1;

$b = ++$a; // $a = $a + 1; $b = $a; -> $a vale 2, y $b 2.

 

2.9.3. Operadores de bits

Veamos ahora los operadores BIT a BIT de que dispone PHP:

 

Operación

Nombre

Resultado

$a & $b

Y

Se ponen a 1 los bits que están a 1 en $a y $b.

$a | $b

O

Se ponen a 1 los bits que están a 1 en $a o $b.

$a ^ $b

O Exclusivo

Se ponen a 1 los bits que están a 1 en $a o $b, pero no en ambos.

~ $a

No

Se invierten los bits (se cambian 1 por 0 y viceversa.)

$a << $b

Desp. Izq.

Desplaza $b posiciones a la izquierda todos los bits de $a.

$a >> $b

Desp. Drch.

Desplaza $b posiciones a la derecha todos los bits de $a.

 

2.9.4. Operadores lógicos

Los operadores lógicos realizan operaciones dependiendo del valor booleano de los operandos.

 

Operación

Nombre

Resultado

$a and $b

Y

Cierto si $a y $b son ciertos.

$a or $b

O

Cierto si $a o $b es cierto.

$a xor $b

O Exclusivo.

Cierto si $a o $b es cierto, pero no ambos.

! $a

No

Cierto si $a es falso.

$a && $b

Y

Cierto si $a y $b son ciertos.

$a || $b

O

Cierto si $a o $b es cierto.

 

La razón de que haya dos operadores distintos para las operaciones Y y O lógicas es que tienen distinta precedencia (ver punto 2.8.9.)

 

2.9.5. Asignación, igualdad e identidad

En PHP hay tres operadores distintos para asignar y comparar valores entre variables, mientras que en ASP todo se realiza con el único operador “=”:

 

Operación

Nombre

Resultado

$a = $b

Asignación

Asigna el valor de una variable o expresión del segundo término a la variable del primer término.

$a == $b

Igualdad

Compara si el valor de los dos operandos es el mismo.

$a === $b

Identidad

Compara si el valor es el mismo y, además, el tipo coincide.

 

Ejemplo:

 

$var1 = 1; // Asignación

$var2 = 1;

$var3 = “1”;

($var1 == $var2) // Cierto, son iguales

($var1 == $var3) // Son iguales (tras la conversión)

($var1 === $var2) // Cierto, son idénticas

($var1 === $var3) // FALSO, el tipo no coincide

 

Los programadores acostumbrados a ASP deben llevar mucho cuidado con esto, ya que puede llevar a errores de este tipo:

 

$var1 = 1;

$var2 = 2;

if( $var1 = $var2 ) {

    echo ‘iguales’;

} else {

    echo ‘distintas’;

}

 

Esta condición en ASP se evaluaría a FALSO. En cambio, en PHP como ‘=’ es el operador de ASIGNACIÓN y no el de IGUALDAD, lo que estamos haciendo es asignar el valor de $var2 a $var1. Tras esto $var1 vale ‘2’, que como es distinto de 1 se evaluará a CIERTO.

 

2.9.6. Comparaciones

Devuelven cierto o falso según el resultado de comparar los dos operandos.

 

Operación

Nombre

Resultado

$a != $b

No igual

Cierto si el valor de $a no es igual al de $b.

$a !== $b

No idéntico

Cierto si $a no es igual a $b, o si no tienen el mismo tipo.

$a < $b

Menor que

Cierto si $a es estrictamente menor que $b.

$a > $b

Mayor que

Cierto si $a es estrictamente mayor que $b.

$a <= $b

Menor o igual que

Cierto si $a es menor o igual que $b.

$a >= $b

Mayor o igual que

Cierto si $a es mayor o igual que $b.

 

La principal diferencia con ASP aquí es que para expresar la desigualdad, en PHP se utilizan “!=” y “!==” mientras que en ASP se utiliza “<>”.

 

También se puede englobar aquí el operador condicional “?:”, que funciona como en C y otros lenguajes:

 

(expr1) ? (expr2) : (expr3);

 

Esta expresión devuelve expr2 si expr1 se evalúa a cierto, o expr3 si expr1 se evalúa a falso. Por ejemplo:

 

$cad = $a > $b ? “a es mayor que b” : “a no es mayor que b”;

 

2.9.7. Operadores de cadenas de texto.

Para operar con cadenas sólo disponemos de un operador: la concatenación de cadenas representada por el punto ‘.’.

 

Ej. :

 

$a = 1;

$b = 2;

$c = ‘El resultado de ‘ . $a . ‘ + ‘ . $b . ‘ es ‘ . $a + b;

 

Que dejaría en $c la cadena “El resultado de 1 + 2 es 3”. Antes de cada concatenación se realizarán las conversiones de tipo que fueran necesarias (en el ejemplo, los enteros se convierten a cadenas.)

 

2.9.8. Atajos en la asignación

Al igual que en C, C++ y Java, en PHP disponemos de una serie de “atajos” para, en una sola operación, operar sobre una variable y asignarle a esa misma variable el resultado.

 

Las operaciones susceptibles de ser usadas en estos atajos son:

 

+  -  *  /  %  &  ^  .  >>  y  <<

 

resultando en los nuevos signos de operación-asignación:

 

          +=  -=  *=  /=  %=  &=  ^=  .=  >>=  y  <<=

 

Ejemplos de uso:

 

$var1 += 3; // $var1 = $var1 + 3;

$var2 /= 2; // $var2 = $var2 / 2;

$var3 >>= 1; // $var3 = $var3 >> 1;

 

2.9.9. Precedencia y asociatividad de operandos

La precedencia de los operandos resuelve el orden en el que se evalúa una expresión múltiple que no ha sido delimitada con paréntesis. Por ejemplo, 1 + 5 * 3 en PHP daría como resultado 1 + (5 * 3) = 16 y no (1 + 5) * 3 = 18 ya que el producto tiene mayor precedencia que la suma.

 

La tabla muestra la asociatividad de los operandos en PHP, y está ordenada en orden decreciente de precedencia (los más prioritarios primero):

 

Asociatividad

Operandos

izquierda

,

izquierda

or

izquierda

xor

izquierda

and

derecha

print

izquierda

= += -= *= /= .= %= &= |= ^= ~= <<= >>=

izquierda

? :

izquierda

||

izquierda

&&

izquierda

|

izquierda

^

izquierda

&

no-asociativo

== != === !==

no-asociativo

< <= > >=

izquierda

<< >>

izquierda

+ - .

izquierda

* / %

derecha

! ~ ++ -- (int) (double) (string) (array) (object) @

derecha

[

no-asociativo

new

 

2.10. Estructuras de control

Las estructuras de control permiten bifurcar el flujo del programa y así ejecutar unas partes u otras del código según ciertas condiciones. PHP dispone de todas las estructuras clásicas de los lenguajes de alto nivel, con la sintaxis de C, C++ o Java, y además algunas otras estructuras más típicas de lenguajes interpretados como Perl o Bash.

 

En todos los casos, las estructuras de control contienen una expresión cuya evaluación a cierto o falso determinará el flujo a seguir dentro de la estructura. Estas expresiones pueden ser una variable, una función (el valor que devuelve), una constante, o cualquier combinación de éstas con los operadores vistos en el punto anterior.

 

2.10.1. if ... elseif ... else

El condicional if es la estructura de control más básica de todas. En su forma más simple, su sintaxis es esta:

 

if (expresión) {

    comandos

}

resto

 

Su funcionamiento es idéntico al de ASP, salvando las diferencias sintácticas: Si expresión se evalúa a cierto, se ejecutan los comandos y después se sigue ejecutando el resto del programa. Si se evalúa a falso, no se ejecutan los comandos y continúa con el resto. Las únicas diferencias con ASP es que expresión debe ir entre paréntesis SIEMPRE, que no hay que poner la palabra THEN y que el cuerpo se delimita con llaves en lugar de con IF .. ENDIF. Estas diferencias de PHP frente a ASP (expresión entre paréntesis y delimitación del cuerpo con llaves) van a ser las mismas para todas las clases de estructuras de control.

 

Las llaves ‘{‘ y ‘}’ no son necesarias (ni en el if ni en ninguna otra sentencia de control) si sólo hay un comando que ejecutar tras la condición, sólo hay que ponerlas para agrupar si hay más de un comando. A pesar de este carácter optativo es aconsejable acostumbrarse a ponerlas siempre, aunque sólo haya un comando que ejecutar, ya que si al continuar el desarrollo se decide añadir un segundo comando (o varios) tras la condición es fácil olvidarse de añadir las llaves y el resultado sería incorrecto.

 

A una sentencia if le podemos añadir código que se ejecute cuando la condición no se verifica mediante la sentencia else:

 

if (expresión) {

    comandos_cierto

} else {

    comandos_falso

}

 

Si expresión se evalúa a cierto, se ejecutan comandos_cierto. Si se evalúa a falso, se ejecuta comandos_falso. En ambos casos luego se ejecuta el resto de comandos que sigan a la instrucción if.

 

Por último, podemos encadenar varias condiciones con la sentencia elseif, de esta forma:

 

if (expresion1) {

    comandos1

} elseif (expresion2) {

    comandos2

} elseif (expresion3) {

    comandos3

}

...

elseif (expresionN) {

    comandosN

} else {

    comandosElse

}

 

El flujo del código comienza evaluando expresión1. Si es cierta, ejecuta comandos1. Si no, evalúa expresión2. Si es cierta, ejecuta expresión2. Si no, evalúa expresión3... y continúa así hasta que alguna de las condiciones de un endif se verifique. Si no se verifica ninguna, se ejecuta comandosElse (este último else es optativo.) En cualquier caso, después se continúa con el flujo normal del programa.

 

2.10.2. while y do .. while

Las estructuras de control while y do .. while representan bucles que se ejecutan mientras se verifique una determinada condición, igual que DO .. LOOP y WHILE .. WEND en ASP. La estructura de un bucle while es esta:

 

while (expresión) {

    comandos

}

 

Y el resultado es que se estará ejecutando toda la serie de sentencias especificada en comandos mientras que expresión se evalúe a cierto.

 

Llegados a este punto hay que hacer notar dos detalles:

 

·        Si la primera vez que el flujo del programa llega a la sentencia while, condición se evalúa a falso, comandos no se ejecuta.

·        Si expresión se evalúa a cierto y dentro de comandos no se modifica el valor de alguna de las variables contenidas en expresión, el código entrará en un bucle infinito (a no ser que algún proceso externo sea el encargado de variar el valor de expresión.)

 

La estructura do .. while puede ser vista como una variante de while en la que la comprobación de la condición se realiza al final de cada iteración del bucle en lugar de al principio. Con esto lo que se consigue es que al menos la iteración se realice siempre una vez, aunque expresión se evalúe a falso. La estructura de do .. while es esta:

 

do {

    comandos

} while (expresión);

 

2.10.3. break y continue

La sentencia break nos permite salir inmediatamente de una estructura de control while, for o switch. Por ejemplo, el siguiente bucle while finalizaría en la iteración $a = 5, pese a que la condición del while es $a < 10:

 

$a = 0;

while ($a < 10) {

    if ($a == 5) {

        break;

    }

    $a++;

}

 

Después del break podemos especificar un parámetro, el número de niveles de bucles anidados de los que queremos salir. Por defecto es uno (salir del bucle más interno) :

 

$a = 0;

while ($a < 10) {

    $b = 0;

 

    while ($b < 5) {

        if ($b == 2) {

            break; // Equivale a “break 1”, sale del while b

        }

    }

 

    while ($b < 5) {

        if ($a == 3 && $b == 3) {

            break 2; // Saldría de los DOS bucles.

        }

    }

}

 

Por su parte, la sentencia continue lo que hace es saltarse el resto de la iteración actual, y pasar directamente a la siguiente:

 

$a = 0;

while ($a < 5) {

    if ($a == 2) {

        continue;

    }

    echo “\$a vale $a.”;

}

 

En el ejemplo se saltaría el echo de la iteración $a = 2, y el resultado sería:

 

$a vale 0

$a vale 1

$a vale 3

$a vale 4

 

2.10.4. for

Los bucles for son los más complejos de que dispone PHP, bastante más que sus homónimos de ASP. Su estructura es la misma que en C:

 

for (expresión1; expresión2; expresión3) {

   comandos

}

 

donde:

 

 

Cualquiera de las tres expresiones puede estar vacía, aunque en este caso tendremos que llevar cuidado de realizar su función en el cuerpo del bucle.

 

Ejemplos:

 

$factorial5 = 1;

for ($i = 2; $i <= 5; $i++ ) {

    $factorial5 *= $i;

}

 

El bucle anterior calcula la factorial de 5 (5!). En expresión1 podemos inicializar varias variables separándolas con comas, con lo que el código se podría rescribir así:

 

for ($factorial5 = 1, $i = 2; $i <= 5; $i++ ) {

    $factorial5 *= $i;

}

 

Por último, en expresión3 también podemos operar sobre varias variables separándolas con comas, con lo que podríamos encerrar todo el código del bucle en la línea for de esta forma:

 

for ($factorial5=1, $i=2; $i<=5; $factorial5*=$i, $i++);

 

En general no se debe complicar tanto un bucle for porque como se ve se pierde bastante en la claridad del código. Esto es un ejemplo tanto de la potencia de los bucles for, como de un mal uso (abuso) de ellos.

 

Los cuatro ejemplos siguientes tienen el mismo resultado: muestran los números del 0 al 10.

 

/* ejemplo 1 */

 

for ($i = 1; $i <= 10; $i++) {

    print $i;

}

 

/* ejemplo 2 */

 

for ($i = 1;;$i++) {

    if ($i > 10) {

        break;

    }

    print $i;

}

 

/* ejemplo 3 */

 

$i = 1;

for (;;) {

    if ($i > 10) {

        break;

    }

    print $i;

    $i++;

}

 

/* ejemplo 4 */

 

for ($i = 1; $i <= 10; print $i, $i++) ;

 

De nuevo, algunos de estos ejemplos (en especial el último) no lo son de buenas costumbres de programación, pero sí de la potencia y flexibilidad del bucle for.

 

Como hemos visto, el bucle for de PHP es MUCHO más potente que el de ASP, así que no debería haber problemas a la hora de pasar bucles de este tipo de ASP a PHP. Valga como ejemplo:

 

’ ASP

<%FOR i=1 TO 100%>

<%=MiVar%>

<%NEXT%>

 

// PHP

<?php

for ($i = 1; $i <= 100; $i++) {

    echo $MiVar;

}

?>

 

2.10.5. foreach

El bucle foreach es nuevo en PHP4, y representa una estructura de control típica de lenguajes interpretados como Perl y Bash, en la que a una variable se le van asignando todos los valores de una lista. Su sintaxis es esta:

 

foreach (array as $variable) {

    comandos

}

 

Es equivalente al FOR EACH .. NEXT de ASP. En cada iteración del bucle, se coloca en $variable un elemento de array, comenzando por el primero y siguiendo un orden ascendente. Por ejemplo:

 

$a = array (1, 2, 3, 17);

 

foreach ($a as $v) {

    print "Valor actual de \$a: $v.\n";

}

 

El resultado sería:

 

Valor actual de $a: 1

Valor actual de $a: 2

Valor actual de $a: 3

Valor actual de $a: 17

 

2.10.6. switch

La estructura switch de PHP es equivalente al SELECT CASE de ASP. Su sintaxis es:

 

switch (variable) {

    case valor1:

 comandos1

    case valor2:

        comandos2

    ...

    case valorN:

        comandosN

    default:

        comandosDefault

}

 

El flujo procede linealmente de arriba a abajo, comparando con cada valor de los case, y ejecutando el código asociado si se cumple la condición. En caso de que no se cumpla ninguna, se ejecuta el código asociado a la cláusula default. El comportamiento sería similar a tener un if por cada case, uno detrás del otro.

 

Hay que destacar como diferencia respecto a ASP que cuando se termina de ejecutar el código de un case, si no se finaliza el switch explícitamente con un break, se continúa ejecutando el código del siguiente case aunque no se cumpla la condición, hasta que se llegue al final del bloque switch o se finalice este con un break. Por ejemplo:

 

switch ($i) {

    case 1:

        echo “Código del 1”;

 

    case 2:

        echo “Código del 2”;

 

    case 3:

        echo “Código del 3”;

        break;

 

    case 4:

        echo “Código del 4”;

}

 

Si $i vale 1, se imprimirán las tres primeras cadenas; Si vale 2, la segunda y la tercera; Si vale 3, sólo la tercera; Y si vale 4, sólo la última.

 

Otro ejemplo del funcionamiento del switch, ahora con una cláusula default:

 

switch ($i) {

    case 0:

    case 1:

    case 2:

    case 3:

        echo “i es menor que 4, pero no negativa”;

        break;

 

    case 4:

        echo “i vale 4”;

        break;

 

    default:

        echo “i mayor que 4 o negativa”;

        break;

}

 

2.11. Evaluaciones a Cierto o Falso

La forma de realizar las comprobaciones booleanas sobre una variable (evaluar su valor a cierto o falso) en PHP puede resultar confusa a los programadores acostumbrados a trabajar con lenguajes fuertemente tipados, ya que antes de realizar la comprobación PHP puede convertir el tipo de la variable. En PHP se puede evaluar de esta forma cualquier variable, contenga un valor del tipo que contenga, lo que lleva a varios tipos de conversión:

 

Para los valores numéricos, 0 es FALSO, cualquier otro valor CIERTO.

 

$x = 1;  // $x 

if( $x ) // se evalúa a cierto

$x = 0;  // $x definida como el entero 0

if( $x ) // se evalúa a falso

 

Para cadenas de texto, una cadena vacía equivale a FALSO, una cadena no vacía a CIERTO.

 

$x = "hello"; // asignamos una cadena a $x

if( $x )      // se evalúa a cierto

$x = "";      // cadena vacía

if( $x )      // evalúa a falso

 

NOTA: $x = “0” es la única excepción, ya que primero se convierte la cadena “0” al decimal 0, que como ya hemos visto se evalúa a FALSO.

 

Para arrays: un array vacío se evalúa a FALSO, mientras que si tiene algún elemento lo hace a CIERTO.

 

$x = array();  // $x es un array vacío

if( $x )       // se evalúa como falso

$x = array( "a", "b", "c" );

if( $x )       // se evalúa a cierto

 

Para objetos, el resultado de la evaluación es FALSO si son objetos vacíos (su clase no define ningún método ni variable), y CIERTO en otro caso.

 

Class Yod {}   // clase vacía

$x = new Yod();

if( $x )       // se evalúa a falso

Class Yod {    // clase no vacía

    var $x = 1;

}

$x = new Yod();

if( $x )       // se evalúa a cierto

 

PHP tiene definidas dos constantes para los valores CIERTO y FALSO, respectivamente TRUE y FALSE. Están definidas de esta forma:

 

 

Es indiferente si se escriben en mayúsculas o minúsculas, es decir, ‘true’, ‘True’ y ‘tRuE’ hacen referencia a la misma constante ‘TRUE’. Para evitar confusiones, escribiremos estas constantes siempre en mayúsculas.

 

Como regla general a utilizar al principio hasta que nos acostumbremos al funcionamiento de PHP, podemos tener en mente esta regla que funciona el 99% de las veces: el valor 0 y la cadena vacía se evalúan a FALSO, cualquier otra cosa a CIERTO.

 

2.12. Funciones

Las funciones de PHP serían el equivalente a los procedimientos SUB y FUNCTION de ASP. Con una función podemos agrupar bajo un nombre una serie de comandos que se repiten a menudo a lo largo del código, y en vez de repetir este código varias veces lo sustituimos por una simple “llamada” a la función.

 

La sintaxis de la declaración de una función en PHP es:

 

function nombre ($arg_1, $arg_2, ..., $arg_n) {

    comandos

    return $salida;

}

 

Los parámetros se pasan por valor, es decir, se crea en $arg_1 ... $arg_n copias locales de las variables, y se trabaja sobre estas copias locales, de forma que al salir de la función los valores originales no han sido modificados. El comando return es opcional, y sirve para que la función devuelva un valor de salida. Es el equivalente a asignar un valor al nombre de la función en ASP. Puede aparecer varias veces en el código de la función, y siempre implica la final de la ejecución de la función. En el cuerpo de la función puede haber cualquier combinación de instrucciones válidas en PHP, incluso otras definiciones de funciones y / o clases. Por ejemplo:

 

function factorial ($valor) {

    if ($valor < 0) {

        return –1; // Error

    }

 

    if ($valor == 0 ) {

        return 1;

    }

 

    if ($valor == 1 || $valor == 2) {

        return $valor;

    }

 

    $ret = 1;

    for ($i = 2; $i <= $valor; $i++) {

        $ret *= $i;

    }

    return $ret;

}

 

$factorial5 = factorial(5);

 

En PHP 3 era necesario definir las funciones antes de usarlas, como en el ejemplo de arriba. Esta restricción se ha eliminado en PHP 4, donde ya se puede utilizar una función antes de su declaración.

 

PHP no soporta sobrecarga de funciones (tener varias funciones con el mismo nombre y distintos argumentos), ni tampoco se puede eliminar o modificar una función previamente definida. Lo que si se puede hacer es dar valores por defecto a algunos de los parámetros que reciba la función (comenzando siempre por la derecha) y hacerlos así optativos:

 

function enlace($url = ”www.php.net”) {

    echo ‘<a href=”’ . $url . ‘”>Pulsa aquí</a>’;

}

 

2.12.1. Paso de parámetros por referencia

Los parámetros de las funciones se pueden pasar por referencia, de forma que si que se pueda modificar su valor dentro de la función. Esto se consigue utilizando el símbolo ‘&’ en la definición de la función, que tiene el mismo efecto que ByRef en ASP:

 

function MiFuncion(&$var) {

    $var++;

}

 

$a = 5;

MiFuncion($a);

// Aquí $a == 6

 

2.12.2. Devolución de variables por referencia

PHP también nos permite devolver variables por referencia. Esto puede ser útil, por ejemplo, cuando tenemos una función que busca un valor dentro de una colección de variables, y queremos que devuelva la variable entera (porque es una estructura que contiene más datos que vamos a necesitar.) En este caso, hay que utilizar el ‘&’ tanto en la definición de la función como en la llamada a ésta:

 

function &buscar_cliente($nombre) {

    // ... buscamos ...

    return $registro;

}

 

$cliente = &buscar_cliente(“Juan”);

echo $cliente->dni;

 

2.13. include y require

La cláusula require(“fichero”); se sustituye en el código antes de que este se ejecute por el contenido de fichero, que puede ser un fichero local o una URL, igual que funciona el #include de C o ASP. Esta sustitución se realiza una sola vez, mientras se está preprocesando el contenido del fichero .php y antes de ejecutarlo.

 

La cláusula include(“fichero”); también se sustituye por el contenido de fichero, pero en lugar de realizarse una única vez durante el preproceso del fichero, se realiza durante la ejecución, cada vez que el flujo del programa llega a esa línea.

 

La utilidad de ambas cláusulas es la misma: imagínese unas líneas de código que se vayan a necesitar en varios ficheros (por ejemplo, una función que valide ciertos datos, o que muestre la cabecera y pie de las páginas). En lugar de copiar ese código en todos los ficheros que lo necesiten, se pone en un fichero que es “incluido” por el resto. Entontes, ¿por qué tener dos funciones distintas para hacer lo mismo? Principalmente por dos motivos:

 

 

También existen las funciones include_once y require_once, que nos aseguran que un determinado fichero sólo será procesado una vez, en caso de que en sucesivos includes vuelva a aparecer.

 

 


3. Programando en PHP

En esta segunda parte del curso, una vez ya tenemos una idea general de cómo se programa en PHP, vamos a olvidarnos de ASP ya estudiar con más detalle algunas de las funciones de PHP que probablemente tendremos que usar con mayor frecuencia.

 

3.1. Forms

Trabajar en PHP con forms es muy fácil, ya que el propio lenguaje se encarga de crear automáticamente las variables necesarias para almacenar los datos del form en la página que los recibe. Vamos a ver algunos ejemplos:

 

3.1.1. Valores sencillos

Para los campos de un formulario en los que únicamente se puede elegir o introducir un valor (como campos de texto, desplegables y “radio buttons”) PHP crea en el fichero de destino tantas variables como campos haya en el formulario, con los nombres que se les haya dado en éste. Por ejemplo, si tenemos este formulario:

 

<form action="accion.php" method="POST">

Su nombre: <input type=text name=nombre><br>

Su edad: <input type=text name=edad><br>

<input type=submit>

</form> 

 

En el script de destino accion.php, accederíamos a los valores enviados en el form así:

 

Hola <?=$nombre?>. 

Tiene <?=$edad?> años. 

 

3.1.2. Valores múltiples

Para los campos de selecciones múltiples PHP también se encarga de almacenar los valores marcados por el usuario en una variable con el nombre del campo, pero en este caso tendremos que llevar cuidado de dar a las variables nombres de arrays, ya que si no sólo tendremos acceso al primer valor seleccionado. Por ejemplo este formulario estaría mal:

 

<form action="accion.php" method="POST">

<select multiple name=menu>

<option>Tortilla <option>Paella

<option>Fabada <option>Lentejas

</select><input type=submit></form> 

 

Deberíamos haberlo escrito así:

 

<form action="accion.php" method="POST">

<select multiple name=menu[]>

<option>Tortilla <option>Paella

<option>Fabada <option>Lentejas

</select><input type=submit></form> 

 

Y podemos ver el resultado con este código:

 

<?php

    echo "Su elección:<br>";

    foreach($menu as $plato) {

        echo "$plato<br>\n";

    }

?> 

 

3.2. Cookies

En PHP podemos almacenar datos en una cookie utilizando la función setcookie():

 

int setcookie (string nombre [, string valor [, int fin

               [, string camino [, string dominio

               [, int seguro]]]]])

 

Como las cookies forman parte de los headers, esta función DEBE ser llamada ANTES de realizar cualquier salida de texto, incluso antes de los tags <html> y <head>. El parámetro fin indica la fecha de expiración de la cookie y se expresa en formato UNIX (como las funciones de PHP time() y mktime()). El parámetro seguro fuerza a que la cookie sólo sea enviada a través de una conexión segura (HTTPS). Los campos optativos de tipo string se pueden omitir poniendo “”, y los numéricos con “0”.

 

Por ejemplo, para definir una cookie llamada “PruebaCookie” con el valor “expiraré dentro de una hora” y que, en efecto, expire en una hora, tendríamos que hacer:

 

setcookie(“PruebaCookie”, “expiraré dentro de una hora”,

          time() + 3600);

 

La próxima vez que se cargue la página, PHP definirá una variable global llamada “PruebaCookie” con el valor definido para ésta.

 

Para borrar la cookie del ejemplo anterior (hay que indicar los mismos parámetros que se usaron para definirla):

 

setcookie(“PruebaCookie”, “”, time());

 

3.3. Sesiones

Para iniciar el seguimiento de una sesión, llamamos a la función session_start():

 

bool session_start(void);

 

Si ya había una sesión (almacenada en una cookie o pasada por GET), la continúa. Si no, crea una nueva.

 

Una vez que hemos iniciado el tratamiento de sesiones, podemos registrar variables en la sesión con session_register():

 

bool session_register (mixed name [, mixed ...])

 

Podemos registrar en una llamada a session_register() tantas variables como queramos.

 

Con estas funciones tenemos la misma restricción que con las cookies: deben llamarse antes de realizar cualquier tipo de salida de texto.

 

Por ejemplo, para implementar un contador del número de veces que un usuario visita una página, podríamos hacer:

 

session_start();

print($contador);

$contador++;

session_register("contador");

 

Para finalizar una sesión, llamamos a session_destroy():

 

bool session_destroy(void);

 

Esta función finaliza la sesión actual, es decir, debe ser llamada siempre después de session_start().

 

El identificador de la sesión se pasa por defecto mediante cookies. Si estas están desactivadas en el cliente, tendremos que pasarlo como una variable GET. PHP define la constante SID con el Session ID actual, de forma que para pasarlo por GET podemos hacer:

 

<A HREF="siguiente_pagina.php?<?=SID?>">Continuar</A>

 

Para más información sobre las funciones de manejo de sesiones disponibles en PHP, está la página del manual:

 

http://www.php.net/manual/ref.session.php

 

3.4. Tratamiento de errores

Para evitar que el cliente reciba mensajes de error internos de PHP (errores con la conexión a la base de datos, por ejemplo) se utiliza el operador ‘@’ delante del comando del que queremos ocultar la salida de error. En caso de error deberíamos tomar alguna acción, como por ejemplo detener la ejecución del script y mostrar un mensaje de error nuestro que tenga algún significado para el cliente. La función die se encarga de hacer esto:

 

$nombre = '/etc/shadow';

$fichero = @fopen ($nombre, 'r');

if (¡$fichero) {

    die("No se pudo abrir el fichero ($nombre)");

}

 

De esta forma, si fopen falla no se muestra en el cliente el mensaje de error que genere, y entonces abortamos la ejecución con la función die.

 

El mensaje de error generado por PHP que ocultamos con el operador ‘@’ se almacena en $php_errormsg si la opción track_errors ha sido activada en el fichero de configuración.

 

Para más opciones en el tratamiento de errores:

 

http://www.php.net/manual/ref.errorfunc.php

 

3.5. Manipulación de strings y arrays

Durante la generación de contenido para páginas Web vamos a estar continuamente trabajando con cadenas de texto: modificándolas, añadiéndoles el valor de algún cálculo interno o algún acceso a una base de datos... Vamos a ver algunas de las funciones más útiles para manipular strings y arrays.

 

3.5.1. Comparaciones

Para comparar cadenas ya hemos visto que podemos utilizar los operadores == y ===, aunque también disponemos de la función strcmp() con el mismo funcionamiento que en C:

 

int strcmp (string str1, string str2)

 

La función devuelve 0 si ambas cadenas son iguales, un número menor que cero si $a es menor que $b, y mayor que cero si $a es mayor que $b. Además, siempre que la cadena contenga algún carácter binario deberemos utilizar esta función en lugar del operador “==”.

 

Por ejemplo:

 

if (strcmp($a, $b) == 0) {

    echo ‘iguales’;

}

 

La función strcmp tiene en cuenta mayúsculas y minúsculas. Si queremos comparar sin tenerlas en cuenta, usaremos strcasecmp:

 

int strcasecmp (string str1, string str2)

 

3.5.2. Subcadenas

Otra operación que podríamos necesitar es obtener una subcadena de otra dada. Esto se consigue con:

 

string substr (string cadena, int inicio [, int tamaño])

 

Si inicio es positivo, devuelve la subcadena que empieza en esa posición. Si es negativo, la subcadena que empieza en esa posición contando desde el final. Si se indica el tamaño, se devuelve una subcadena de hasta ese número de caracteres. Si el tamaño es negativo, se elimina ese número de caracteres de la subcadena devuelta:

 

$str = substr('abcdef', 2, 3);   // cde

$str = substr('abcdef', -2);     // ef

$str = substr('abcdef', -2, 1);  // e

$str = substr('abcdef', 1, -2);  // bcd

 

En ocasiones puede que no sepamos la posición exacta en la cadena de lo que andamos buscando, pero si una serie de caracteres de referencia que marcarán su inicio. Entonces podremos usar estas funciones:

 

int strpos (string cadena, string referencia [, int inicio])

int strrpos (string cadena, char referencia)

string strstr (string cadena, string referencia)

 

La primera función devuelve el índice de la primera ocurrencia de la cadena referencia en cadena a partir de la posición inicio. La segunda función es similar pero aquí referencia es un carácter en lugar de una cadena (si se pasa una cadena sólo se usará el primer carácter), y se busca desde el final de la cadena. Por último, la tercera función devuelve la subcadena de cadena que comienza en la primera ocurrencia de referencia.

 

$i = strpos('cadena de prueba', 'de');

// $i = 2

 

$i = strpos('cadena de prueba', 'de', 5);

// $i = 7

 

$s = strrpos('cadena de prueba', 'de');

// $i = 7

 

$s = strstr('cadena de prueba', 'de');

// $s = dena de prueba

 

3.5.3. Imprimir y formatear cadenas

Se puede formatear e imprimir una cadena con la función printf(), al igual que en C:

 

int printf (string formato [, mixed args...])

 

Aquí, formato es una cadena que puede contener cualquier carácter excepto ‘%’, que se imprimirán tal cual, y secuencias de formato que comienzan por ‘%’ y controlan cómo se mostrarán los argumentos. Estas secuencias de formato se componen de:

 

  1. Un carácter opcional que se utilizará para rellenar y ajustar el tamaño del campo. Por ejemplo, un espacio para caracteres o un cero para números. Por defecto se usa el espacio.
  2. Un indicador opcional para especificar si se alineará a la izquierda (-). Por defecto se alinea a la derecha.
  3. El número mínimo de caracteres que ocupará el campo tras la conversión. También es opcional.
  4. Un indicador opcional de precisión, formado por un punto seguido del número de dígitos decimales que se deberán mostrar con los números en punto flotante. No tiene efecto con otros tipos de datos.
  5. Un indicador de tipo que especifica cómo se deberá tratar el dato. Los tipos disponibles son:

% El carácter de tanto por ciento.

b El argumento se trata como entero y se muestra en binario.

c Se trata como entero, y se muestra el carácter ASCII.

d Se trata como entero y se muestra el número en decimal.

f Se trata como double, y se muestra como punto flotante.

o Se trata como entero y se muestra en octal.

s El argumento se trata y se muestra como una cadena.

x Se trata como entero y se muestra en hexadecimal (con las letras en minúsculas).

X Se trata como entero y se muestra en hexadecimal (con las letras en mayúsculas).

 

Ejemplos:

 

printf(“%02d/%02d/%04d”, $dia, $mes, $año);

 

$pago1 = 68.75;

$pago2 = 54.35;

$pago = $pago1 + $pago2;

// echo $pago mostrará "123.1"

// Mostrar al menos un dígito entero y exactamente dos

// decimales, rellenando con ceros

printf ("%01.2f", $pago);

 

También podemos almacenar el resultado del formateo en una cadena en lugar de imprimirlo con la función sprintf():

 

string sprintf (string formato [, mixed args...])

 

El formato es el mismo que con printf:

 

$fecha = sprintf(“%02d/%02d/%04d”, $dia, $mes, $año);

 

Estas dos funciones son muy útiles a la hora de dar un formato específico a unos datos, pero se debe de huir de ellas cuando este formato no sea importante o simplemente no se esté realizando ningún formateo, ya que es mucho más rápido imprimir con echo o concatenar cadenas con el operador ‘.’.

 

3.5.4. Escapar caracteres

PHP tiene varias funciones para “escapar” con barras invertidas algunos caracteres que bajo ciertas circunstancias pueden dar problemas. Por ejemplo, en SQL tendremos que escapar los apóstrofes en las restricciones de un WHERE, pero si por ejemplo estas restricciones las hemos obtenido por parte del usuario (en un form), no sabemos a priori si habrá algún carácter que escapar ni dónde. Con la función addslashes() podemos manejar este tipo de situaciones, ya que se encarga de añadir las barras invertidas que haga falta:

 

$busca = “D’Alton”; // Habrá que escapar el apóstrofe

$sql = ‘SELECT * FROM usuarios WHERE apellido = \’’ .

        addslashes($busca) . ‘\’’;

 

Otro caso en el que escapar caracteres es MUY importante es a la hora de realizar llamadas al sistema. En PHP podemos ejecutar cualquier comando en el servidor con la función system():

 

string system (string comando [, int valor_salida])

 

Por ejemplo, podríamos tener una página en la que en un form se pida el nombre de un usuario de nuestro sistema, y que devuelva la información de finger sobre ese usuario. Si lo hiciéramos simplemente así:

 

echo system(“finger $usuario”);

 

y en $usuario tenemos la entrada del form sin más, tendríamos un grave agujero de seguridad, ya que si en el form por ejemplo nos hubieran puesto “pepe ; apachectl stop” y PHP se estuviera ejecutando como root cualquiera nos podría detener Apache. Para evitar esto habría que aplicar esta función sobre los datos que recibamos del form:

 

string escapeshellcmd (string comando)

 

que se encarga de escapar con barras los caracteres que se podrían usar en el shell de UNIX para ejecutar un programa sin nuestro permiso (en concreto, #&;´'\"|*?~<>^()[]{}$\\\x0A\xFF).

 

Además de por razones de seguridad, también necesitaremos a veces cambiar unos caracteres por otros para formatear correctamente un texto en HTML. Esto lo hace la función htmlspecialchars():

 

$valor = “a>b”;

echo ‘<input type=hidden name=var value=”’ . 

     htmlspecialchars($valor) . ‘”>’;

// <input type=hidden name=var value=”a&gt;b”>

 

Podemos también convertir todos los caracteres de fin de línea de una cadena a “<br>” con:

 

string nl2br (string cadena)

 

3.5.5. Extraer campos

Podemos dividir una cadena formateada en campos divididos por un delimitador en un array de cadenas con esos campos usando la función explode():

 

array explode (string delimitador, string cadena

               [, int límite])

 

Si se especifica un límite, se extraerá hasta ese número de campos y en el último estará el resto de la cadena.

 

Por ejemplo, en UNIX se utiliza bastante el carácter de dos puntos para separar campos en una cadena, por ejemplo en el fichero /etc/passwd. Podemos utilizar esta función para obtener el valor de cada campo.

 

$cadena = “campo1:campo2:campo3”;

$campos = explode(“:”, $cadena);

 

La operación inversa, por la que a partir de un array de campos y un separador se junta todo en una sola cadena, es implode():

 

string implode (string delimitador, array campos)

 

Para volver a la cadena original del ejemplo anterior, usaríamos:

 

$cadena = implode(“:”, $campos);

 

En caso de que delimitador no siempre sea el mismo carácter, tendremos que recurrir a split, cuyo funcionamiento es similar al de explode pero utiliza expresiones regulares para dividir los campos:

 

array split (string delimitador, string cadena

             [, int límite])

 

Por ejemplo, para obtener los campos de una fecha donde el día, mes y año puedan estar separados por espacios, barras, guiones o puntos, tendríamos que utilizar split así:

 

$fecha = "12/4 2000";

$campos = split ('[ /.-]', $fecha);

 

3.5.6. Recorrer un array

Todos los arrays de PHP disponen de un puntero que señala al elemento actual, puntero que sirve para recorrer el array secuencialmente con las funciones current(), next(), prev(), reset() y end(), que devuelven el elemento actual, siguiente, anterior, inicial o final del array, y a la vez actualizan el puntero a esa posición. También disponemos de las funciones key(), que devuelve el índice (numérico o asociativo) del elemento actual; y each(), que devuelve un array con el índice del elemento actual en las posiciones 0 y ‘key’, y su valor (lo mismo que devolvería current) en las posiciones 1 y ‘value’, y actualiza el puntero actual al siguiente (lo que haría next).

 

Por ejemplo:

 

$arr = array(1,'cosa',1.57,'gato'=>'raton','perro'=>'gato');

 

current($arr); // 1

next($arr);   // cosa

current($arr);   // cosa

prev($arr);   // 1

end($arr);   // gato

current($arr);   // gato

key($arr);   // perro

reset($arr);   // 1

each($arr);   // array(0,1)

each($arr);   // array(1,'foo')

each($arr);   // array(2,1.57)

 

Este puntero al elemento actual del que estamos hablando también se utiliza en los bucles foreach y se actualiza en cada iteración.

 

3.5.7. Ordenar un array

En PHP tenemos varias funciones para ordenar un array:

 

·        sort():          Ordena el array por contenido en orden ascendente.

·        rsort():          Ordena por contenido en orden descendente.

·        ksort():          Ordena por el índice en orden ascendente.

·        rksort():          Ordena por el índice en orden descendente.

 

3.5.8. Otras funciones útiles

Una operación útil puede ser eliminar los espacios que haya al principio o final de una cadena, por ejemplo si vamos a pasar el texto que ha escrito un usuario en un form a un query en SQL. Esto lo conseguimos con trim:

 

string trim (string cadena)

 

Esta función elimina espacios del principio y final de la cadena. También se puede usar ltrim y rtrim, que los eliminan sólo del inicio y sólo del final, respectivamente.

 

Podemos convertir una cadena a mayúsculas con:

 

string strtoupper (string cadena)

 

Y a minúsculas con:

 

string strtolower (string cadena)

 

También puede ser útil convertir a mayúsculas tan sólo el primer carácter de la cadena, por ejemplo si estamos construyendo frases. Esto se consigue con:

 

string ucfirst (string cadena)

 

3.5.7. Más información

Para más información sobre todas las funciones de strings y arrays disponibles en PHP, ver las páginas de manual:

 

http://www.php.net/manual/ref.strings.php

 

http://www.php.net/manual/ref.array.php

 

3.6. Manejo de Ficheros

En algunos casos necesitaremos tratar con ficheros y directorios en el sistema local. PHP dispone de toda una serie de funciones para manipularlos, muy similares en sintaxis y uso a las de la librería stdio.h de C. Para obtener más información de todas las funciones de ficheros y directorios disponibles, consultar las páginas del manual:

 

 

3.6.1. Abrir y cerrar un fichero

Para abrir un fichero tenemos la función fopen():

 

int fopen (string nombre, string modo [, int include_path])

 

Esta función abre el fichero nombre (que puede ser local o remoto, si se indica con “http://” o “ftp://”) según modo:

 

·        'r' – Modo de sólo lectura. El puntero se coloca al inicio del fichero.

·        'r+' – Modo lectura/escritura. El puntero se coloca al inicio.

·        'w' – Modo de sólo escritura. Si el fichero existe, se borran sus contenidos. Si no existe, se crea.

·        'w+' – Modo lectura/escritura. Si el fichero existe, se borran sus contenidos. Si no existe, se crea.

·        'a' – Modo sólo escritura. Si el fichero existe, el puntero se coloca al final del fichero. Si no existe se crea.

·        'a+' – Modo lectura/escritura. Se coloca el puntero al final del fichero. Si no existe se crea.

 

Si el último parámetro se pone a 1, se buscará los ficheros además de en el directorio actual en el indicado en la opción de configuración include_path en php.ini.

 

La función devuelve un identificador para usar con el resto de funciones, o FALSE si ha habido un error.

 

Para cerrar el fichero, se usa fclose() con el identificador devuelto por fopen():

 

int fclose (int identificador)

 

3.6.2. Leer y escribir en el fichero

Se puede leer toda una línea de un fichero con la función fgets():

 

string fgets (int identificador, int tamaño)

 

que devuelve la siguiente línea del fichero apuntado por identificador, o tamaño – 1 caracteres si la línea era más larga.

 

También se puede leer y a la vez ir procesando la entrada de acuerdo a un formato determinado y almacenándola en variables con la función fscanf(), que sigue el mismo formato de printf:

 

mixed fscanf (int identificador, string formato

              [, string var1...])

 

Para controlar si hemos llegado al final del fichero, debemos usar feof(), que devuelve TRUE si se ha llegado al final o ha habido un error, o FALSE en otro caso:

 

int feof (int identificador)

 

Podemos leer todo el contenido de un fichero con la función file(), que no necesita de un fopen() y almacena el contenido del fichero leído línea a línea en un array:

 

array file (string fichero [, int include_path])

 

Para escribir en un fichero, usaremos fwrite():

 

int fwrite (int identificador, string cadena [, int tamaño])

 

que escribe en el fichero apuntado por identificador el contenido del string cadena, o tamaño bytes si cadena era más larga.

 

3.6.3. Copiar / renombrar / borrar ficheros

Podemos copiar un fichero con:

 

int copy (string origen, string destino)

 

renombrarlo (moverlo) con:

 

int rename (string origen, string destino)

 

o borrarlo con:

 

int unlink (string fichero)

 

3.6.4. Directorios

Para movernos a otro directorio, tenemos la función chdir():

 

int chdir (string directorio)

 

Para crear un directorio llamaremos a mkdir():

 

int mkdir (string nombre, int modo)

 

donde modo indica los permisos (en formato UNIX).

 

Y para borrar directorios:

 

int rmdir (string nombre)

 

Si queremos saber qué ficheros hay dentro de un directorio (como hacer un “dir” en DOS o un “ls” en UNIX), tenemos que usar las funciones opendir() para abrirlo, readdir() para ir viendo los contenidos y closedir() para cerrarlo. Estos son los formatos de estas funciones:

 

int opendir (string nombre)

string readdir (int identificador)

void closedir (int identificador)

 

Por ejemplo, para mostrar la lista de ficheros en el directorio actual, tendríamos que hacer algo así:

 

$direcotrio = opendir('.');

while (($fichero = readdir($directorio)) !== FALSE) {

    echo "$fichero\n";

}

closedir($directorio);

 

3.6.5. Envío de ficheros

Podemos generar formularios para que el usuario seleccione un fichero en su equipo local y el cliente nos lo envíe por el método POST:

 

<FORM ENCTYPE="multipart/form-data"

      ACTION="recibir.php" METHOD=POST>

<INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="1000">

Fichero: <INPUT NAME="fichero" TYPE="file">

<INPUT TYPE="submit" VALUE="Enviar">

</FORM>   

 

En el ejemplo, recibir.php sería el script .php encargado de tratar con el fichero recién enviado y el valor del campo oculto MAX_FILE_SIZE es el tamaño máximo (en bytes) que admitiremos. En el script de destino se crearán de forma automática estas variables, según el nombre indicado en el form:

 

 

En el script que recibe el fichero se deberá implementar toda la lógica necesaria para ver qué se hace con el fichero, ya que al finalizar su ejecución el fichero temporal se borra del sistema. Por ejemplo, podríamos decidir simplemente almacenar el fichero en el directorio actual, para lo que podríamos utilizar este código:

 

echo ’Recibido el fichero: "’ . $fichero_name . ’"<br>’;

echo ’Tamaño del fichero: ’ . $fichero_size . ’<br>’;

echo ’Tipo mime: ’ . $fichero_type . ’<br>’;

rename($fichero, $fichero_name);

 

3.7. POO: Clases y Objetos

La idea fundamental de la Programación Orientada a Objetos es la de encapsular en una misma entidad (un objeto) una serie de datos que definan su estado (variables de instancia) y las funciones encargadas de acceder a esos datos (métodos.) Las clases son las definiciones de la estructura (variables y métodos) de los objetos, y estarían un escalón por arriba de las estructuras simples de los lenguajes de alto nivel (p. Ej. los struct de C) y los TADs.

 

Con esta encapsulación lo que se consigue es que cada objeto de una determinada clase funcione como una caja negra de la que poco nos importa su implementación interna. Cuando trabajamos con un objeto de la clase “coche” nos da igual cómo funcione internamente el método “acelerar”. Tan sólo sabemos que nuestro coche puede acelerar, y sabemos cuál será el resultado, sin preocuparnos del proceso interno que se siga para conseguir este fin. De esta forma se independiza la implementación de la clase, del uso de sus objetos, y el flujo del programa pasa de ser procedural a convertirse en un diálogo entre objetos que interactúan entre sí.

 

PHP no es un Lenguaje Orientado a Objetos puro, ya que presenta ciertas carencias, aunque aporta las suficientes características de los LOO para poder hacer un diseño e implementación basado en objetos.

 

3.7.1. Definición de una clase

La sintaxis para la declaración de clases en PHP es similar a la de C++ o Java:

 

class NombreClase {

    var $variables;

  

    function metodos ($parametros) {

        codigo

    }

}

 

La definición de las variables dentro de una clase es el único caso en PHP en el que SI que hay que declarar explícitamente una variable antes de usarla, y se hace con la palabra reservada var.

 

Una de las carencias de las clases de PHP es que no se puede restringir el acceso a las variables y métodos. En los LOO puros, hay una serie de palabras reservadas (p.ej., public, private y protected en C++) para indicar si a una variable o método es público y se puede acceder desde fuera, o si es privado y sólo se puede acceder de forma interna desde otros métodos de la propia clase o sus derivadas (protegido).

 

Para acceder a las variables y métodos de un objeto, tanto desde fuera como desde un método del propio objeto, hay que utilizar el operador “->”, sobre el nombre de la variable que almacena el objeto si accedemos desde fuera ($miCasa->telefono), o sobre la referencia al propio objeto $this si es desde dentro ($this->telefono.)

 

Existe una clase especial de métodos, llamados constructores, que se llaman igual que la clase y se invocan de forma automática al crear un objeto. Estos constructores se encargan de inicializar los valores de las variables internas, reservar memoria, crear estructuras de datos que se vayan a utilizar después... Los constructores pueden tener o no tener parámetros, que habrá que pasar en la creación del objeto.

 

Como ejemplo, vamos a definir una clase “coche”:

 

class Coche {

    var $velocidad; // Velocidad actual

 

    // Constructor por defecto. El coche está parado.

    function Coche() {

        $this->velocidad = 0;

    }

 

    // Constructor que indica la velocidad inicial.

    function Coche($vel) {

        $this->velocidad = $vel;

    }

 

    // Método acelerar. El coche va más rápido.

    function acelerar() {

        $this->velocidad++;

    }

 

    // Método frenar. El coche va más lento hasta frenar.

    function frenar() {

        if ($this->velocidad > 0) {

            $this->velocidad--;

        }

    }

}

 

3.7.2. Herencia

Otra de las características más importantes de la POO junto con la encapsulación es la herencia, por la que se pueden definir clases derivadas de otras ya existentes. Estas clases derivadas (subclases) “heredan” todas las características (variables) y funcionalidad (métodos) de sus clases “madres” (superclases). Es una forma de ir especializando el tipo de cada clase, partiendo de una clase muy genérica hasta las herederas más específicas.

 

Para definir una clase en función de otra, se usa la palabra reservada extends en la definición de la subclase. De esta forma, la clase heredera parte ya con todas las variables y métodos de su superclase, y además podrá añadir tantas variables y métodos como quiera e incluso redefinir algún método en el proceso de especialización de las clases.

 

Vamos a definir una subclase de coche llamada cocheFantastico, que será capaz de hablar, saltar, poner el turbo y que además en lugar de frenar poco a poco frenará de golpe:

 

class CocheFantastico extends coche() {

    // Frenado instantáneo

    function frena() {

        $this->velocidad = 0;

    }

 

    // ¡El coche habla!

    function habla() {

        echo “Hola, Michael.”;

    }

 

    // ¡Salta!

    function salta() {

        echo “Boing!!”;

    }

 

    // Turbo propulsión

    function turbo() {

        $this->velocidad = 200;

    }

}

 

IMPORTANTE: si se redefinen los constructores, el de la superclase NO SE LLAMA AUTOMÁTICAMENTE al llamar al de la subclase.

 

3.7.3. Creación y uso de objetos

Los objetos se crean con el operador new y el nombre de la clase, y se asignan a una variable para poder usarlos:

 

$MiCoche = new Coche;

 

Si queremos pasarle parámetros a algún constructor, los parámetros se indican entre paréntesis tras el nombre de la clase:

 

$MiCocheSeMueve = new Coche(10);

 

Para acceder a las variables o métodos del objeto, utilizamos el operador “->” sobre el nombre de la variable:

 

$MiCoche->acelerar();

$MiCoche->acelerar();

$MiCoche->acelerar();

echo $MiCoche->velocidad;

$MiCoche->frenar();

 

3.7.4. Datos sobre las clases/objetos

En PHP tenemos una serie de funciones para obtener más información sobre una determinada clase o un objeto. Están detalladas en la siguiente página del manual:

 

          http://www.php.net/manual/ref.classobj.php

 

3.8. Acceso a Bases de Datos

PHP dispone de varias funciones para acceder a Bases de Datos, pero son propias de cada una de estas Bases de Datos, es decir, no hay una función “conectar” genérica, si no una para conectar a MySQL, otra para conectar a Informix, etc. Para evitar confusiones entre las funciones de unas BD y otras, el nombre de todas estas funciones sigue este patrón:

 

<nombreBD>_<nombreFUNCION>

 

de forma que tenemos una función mysql_connect, una función ifx_connect... Todas las funciones con el mismo nombre de función pero para distintas BD comparten la misma funcionalidad y parámetros. Lo único que tendremos que comprobar es que una determinada función esté disponible para la BD que vamos a atacar, ya que dependiendo de la BD y de su grado de integración con PHP tendremos más o menos funciones.

 

Vamos a explicar las funciones más importantes, con ejemplos en MySQL ya que es la BD que mejor integrada está en PHP. Se puede obtener una lista completa de todas las opciones en el manual de PHP:

 

http://www.php.net/manual/ref.mysql.php

 

o en las páginas de funciones de las otras BD.

 

3.8.1. Abrir y cerrar una conexión

Para conectar a una BD tenemos la función mysql_connect con la siguiente definición:

 

int mysql_connect ([string servidor [:puerto] [:/camino/al/socket]

                   [, string usuario [, string contraseña]]])

 

Todos los parámetros son opcionales. Si no se indican, se utiliza “localhost” como servidor por defecto, el nombre del usuario que esté ejecutando PHP como usuario, y la cadena vacía como contraseña. La función devuelve un identificador de la conexión que necesitaremos más tarde para hacer referencia a este enlace en concreto con la BD, o un error si algo ha ido mal.

 

La conexión con la BD se cierra automáticamente al finalizar la ejecución del fichero actual. También se puede cerrar explícitamente con mysql_close:

 

int mysql_close ([int identificador])

 

Esta función cierra la conexión indicada por el identificador o la última conexión que se haya abierto si se omite, y devuelve TRUE o FALSE según si la operación ha finalizado con éxito o no. Por ejemplo, así nos conectaríamos a la BD MySQL en el servidor linux:

 

$link = mysql_connect ("www.mmlabx.ua.es", "nobody", "");

if (!$link) {

    die ("No se pudo conectar");

}

print ("Conexión realizada");

mysql_close ($link);

 

Con algunas BD también se pueden usar enlaces persistentes que no se cerrarán automáticamente al acabar la ejecución del fichero, si no que permanecerán abiertos y se podrán utilizar desde los siguientes ficheros .php que se ejecuten. Estos enlaces se abren y cierran con mysql_pconnect y mysql_pclose. Su definición es idéntica a la de connect y close:

 

int mysql_pconnect ([string servidor [:puerto][:/camino/al/socket]

                    [, string usuario [, string contraseña]]])

 

int mysql_pclose ([int identificador])

 

3.8.2. Elegir una BD

Para elegir la base de datos con la que queremos trabajar de entre todas las disponibles se utiliza la función mysql_select_db:

 

int mysql_select_db (string nombre_bd [, int identificador])

 

Aquí, nombre_bd especifica el nombre de la BD a la que queremos acceder, y el campo opcional identificador es el número de identificación de enlace devuelto por mysql_connect. Si se omite este último campo, se utiliza el último enlace abierto, y si no existiera, se trata de crear uno con mysql_connect (sin parámetros). La función devuelve TRUE o FALSE, según si todo ha ido bien o no.

 

Para elegir la BD “prueba” utilizada en el sistema de gestión de asignaturas en nuestro servidor Linux, utilizaríamos:

 

if (!mysql_select_db("prueba", $link)) {

    die (“No existe la BD”);

}

 

3.8.3. Interrogar a la BD

Para hacer querys a una BD se utiliza mysql_query:

 

int mysql_query (string query [, int identificador])

 

En query va la sentencia en SQL que queremos ejecutar. Al igual que con mysql_select_db, si se omite el identificador se usa el último o se trata de crear. Esta función devuelve FALSE si ha habido un error, o un valor no negativo (TRUE) que identifica el resultado y que más tarde deberá ser tratado para extraer la información necesaria.

 

Para obtener la información de las asignaturas en la BD de ejemplo:

 

$query = "SELECT codigo, nombre, descripcion, creditos, tipo

                 FROM asignatura";

$asignaturas = mysql_query($query, $link);

if (!$asignaturas) {

   die (“Error en el query”);

}

 

También podemos utilizar esta otra función, en la que además del query indicamos la BD a la que queremos interrogar:

 

int mysql_db_query (string nombre_bd, string query

                    [, int identificador])

 

Cuando hayamos acabado con el resultado, podemos liberar memoria con:

 

int mysql_free_result (int result)

 

aunque realmente no es necesario ya que el recolector de basura de PHP se encargará de liberarla al acabar la ejecución del fichero actual.

 

3.8.4. Extraer información del resultado del query

Si la última operación fue un INSERT, UPDATE o DELETE (operaciones que modifican algún registro), se puede utilizar esta función para ver el número de filas afectadas:

 

int mysql_affected_rows ([int identificador])

 

Para obtener el número de filas en el resultado de un query, tenemos:

 

int mysql_num_rows (int resultado)

 

Donde resultado es el valor devuelto por mysql_query.

 

Para obtener toda una fila del resultado:

 

array mysql_fetch_row (int resultado)

 

Cada llamada sucesiva a esta función devuelve un array con la siguiente fila del resultado, hasta que no queden filas y devuelva FALSE. Las columnas están indexadas por orden en el array, comenzando la primera en la posición 0.

 

Para este mismo fin también disponemos de otra función, que es una extensión de la anterior:

 

array mysql_fetch_array(int resultado [, int tipo_resultado])

 

Esta función es capaz de indexar el array de forma numérica o asociativa por el nombre de las columnas. El parámetro tipo_resultado puede valer MYSQL_ASSOC, MYSQL_NUM, o MYSQL_BOTH para indicar el tipo de indexado que queremos (por defecto, ambos). Hay que destacar que, a pesar de la funcionalidad extendida sobre mysq_fetch_row, esta función NO es significativamente más lenta que la anterior.

 

Continuando con el ejemplo anterior, podemos obtener los resultados del query así:

 

while ($fila = mysql_fetch_array($asignaturas)) {

    echo $fila[‘codigo’] . ‘ ‘ . $fila[‘nombre’] . “\n”;

}

 

Otra función que podemos utilizar para obtener los resultados de un query es mysq_fetch_object:

 

object mysql_fetch_object (int result)

 

que en lugar de almacenar el resultado en un array, lo almacena en un objeto cuyas propiedades (variables) coinciden con los nombres de las columnas:

 

while ($fila = mysql_fetch_object($asignaturas)) {

    echo $fila->codigo . ‘ ‘ . $fila->nombre . “\n”;

}

 

Si queremos saber el tamaño de los campos de la última fila devuelta por mysql_fetch_array, object o row, tenemos:

 

array mysql_fetch_lengths (int resultado)

 

Esta función devuelve un array con tantos campos como columnas el último resultado, con los tamaños de estas columnas.

 

Por último, podemos “saltar” directamente a una fila del resultado, o “rebobinar” una vez hemos llegado al final, con la función mysql_data_seek. Las filas comienzan en el 0.

 

int mysql_data_seek (int resultado, int numero_fila)

 

3.9. Acceso a Bases de Datos unificado

Hemos ideado un método para reducir al mínimo las modificaciones en el código al cambiar de Sistema Gestor de Bases de Datos. El método utiliza la POO para definir una clase “virtual” que define un interfaz genérico de acceso a bases de datos, clase de la que luego heredarán este interfaz las clases especializadas en el acceso a cada BD en concreto. En nuestro programa utilizaremos objetos de estas clases especializadas para acceder a las BD, pero como todos ellos compartirán los mismos métodos, la única línea de código que habrá que cambiar será aquella en la que se cree el objeto de una clase (BD) u otra. Y para no tener que modificar esta línea en todos los ficheros, tendremos un fichero en el que se crea el objeto y se incluirá desde todos los demás. De esta forma, tendremos un objeto accesible en todos los ficheros y sólo tendremos que modificar uno para cambiar de BD.

 

Este es el código de la clase ConexionGenerica. Define el interfaz que será comun a todas las clases específicas de cada BD, y provee ya de mensajes de error para el caso de que una clase no defina un método en concreto:

 

 

<?php

 

/*

 * Clase base para definir una conexión genérica a una BD desde PHP.

 * Se deberán definir clases que hereden de esta redefiniendo sus métodos

 * para cada BD a la que queramos acceder.

 *

 * Vicente Aguilar <vaguilar@linuxfreak.com>

 *

 * 7/9/2000

 */

 

 

/**

 * CLASE ConexionGenerica

 *

 * Esta clase es una plantilla para definir la estructura básica (variables

 * y métodos) de todas las clases para conectar a distintas BBDD que más

 * tarde heredarán de esta, redefiniendo los métodos.

 */

class ConexionGenerica {

 

      /** El enlace con la BD */

      var $link;

 

      /**

     * Constructor. No hace nada. Creo que se podría quitar ...

       */

      function ConexionGenerica() {}

 

      /**

       * FUNCIÓN connect( servidor, usuario, clave )

     * Conecta con el servidor, identificándose como usuario y clave.

       * No hace nada, debe ser redefinida por las clases que hereden de esta.

       */

      function connect($servidor, $usuario, $clave) {

            echo "<h1>El m&eacute;todo <i>connect</i> no est&aacute; " .

                 "implementado en la clase <i>" . get_class($this) . "</i></h1>";

            return FALSE;

      }

 

      /**

       * FUNCIÓN close()

       * Finaliza la conexion con el servidor.

       * No hace nada, debe ser redefinida por las clases que hereden de esta.

       */

      function close() {

            echo "<h1>El m&eacute;todo <i>close</i> no est&aacute; " .

                 "implementado en la clase <i>" . get_class($this) . "</i></h1>";

            return FALSE;

      }

 

      /**

       * FUNCIÓN select_db( base_datos )

       * Elige la base de datos con la que trabajar.

       * No hace nada, debe ser redefinida por las clases que hereden de esta.

       */

      function select_db($base_datos) {

            echo "<h1>El m&eacute;todo <i>select_db</i> no est&aacute; " .

                 "implementado en la clase <i>" . get_class($this) . "</i></h1>";

            return FALSE;

      }

 

      /**

       * FUNCIÓN query( query )

       * Realiza una consulta o actualización en la BD.

       * No hace nada, debe ser redefinida por las clases que hereden de esta.

       */

      function query($query) {

            echo "<h1>El m&eacute;todo <i>query</i> no est&aacute; " .

                 "implementado en la clase <i>" . get_class($this) . "</i></h1>";

            return FALSE;

      }

 

      /**

       * FUNCIÓN fetch_array( resultado )

       * Realiza una consulta o actualización en la BD.

       * No hace nada, debe ser redefinida por las clases que hereden de esta.

       */

      function fetch_array($resultado) {

            echo "<h1>El m&eacute;todo <i>query</i> no est&aacute; " .

                 "implementado en la clase <i>" . get_class($this) . "</i></h1>";

            return FALSE;

      }

 

      /**

       * FUNCIÓN free_result( resultado )

       * Libera la memoria ocupada por un resultado.

       * No hace nada, debe ser redefinida por las clases que hereden de esta.

       */

      function free_result($resultado) {

            echo "<h1>El m&eacute;todo <i>free_result</i> no est&aacute; " .

                 "implementado en la clase <i>" . get_class($this) . "</i></h1>";

            return FALSE;

      }

}

 

?>

 

Un ejemplo de clase especializada en una BD sería la siguiente para MySQL:

 

<?php

 

/*

 * Clase para conectar a una base de datos MySQL.

 * Hereda de ConexionGenerica y redefine sus métodos de acceso a la BD.

 *

 * Vicente Aguilar <vaguilar@linuxfreak.com>

 *

 * 7/9/2000

 */

 

// La clase "plantilla" de la que heredamos

require ("ConexionGenerica.inc");

 

/**

 * CLASE ConexionMySQL

 * Métodos para conectar e interactuar con una BD MySQL.

 */

class ConexionMySQL extends ConexionGenerica {

 

      /**

     * Constructor. No hace nada. Creo que se podría quitar ...

       */

      function ConexionMySQL() {}

 

      /**

       * FUNCIÓN connect( servidor, usuario, clave )

     * Conecta con el servidor, identificándose como usuario y clave.

       */

      function connect($servidor="localhost", $usuario="nobody", $clave="") {

            return $this->link = mysql_connect($servidor, $usuario, $clave);

      }

 

      /**

       * FUNCIÓN close()

       * Finaliza la conexion con el servidor.

       */

      function close() {

            return mysql_close($this->link);

      }

 

      /**

       * FUNCIÓN select_db( base_datos )

       * Elige la base de datos con la que trabajar.

       */

      function select_db($base_datos) {

            return mysql_select_db($base_datos, $this->link);

      }

 

      /**

       * FUNCIÓN query( query )

       * Realiza una consulta o actualización en la BD.

       */

      function query($query) {

            return mysql_query($query, $this->link);

      }

 

      /**

       * FUNCIÓN fetch_array( resultado )

       * Realiza una consulta o actualización en la BD.

       */

      function fetch_array($resultado) {

            return mysql_fetch_array($resultado);

      }

 

      /**

       * FUNCIÓN free_result( resultado )

       * Libera la memoria ocupada por un resultado.

       */

      function free_result($resultado) {

            return mysql_free_result($resultado);

      }

}

 

?>

 

Además de estas dos clases, tenemos otro fichero CreaConexion.inc que es el encargado de crear el objeto de la clase que vayamos a usar:

 

<?php

 

/**

 * CreaConexion

 * Crea una conexion (variable $conexion) con una base de datos.

 *

 * Vicente Aguilar <vaguilar@linuxfreak.com>

 *

 * 7/9/2000

 */

 

/*

 * Habra que cambiar estas dos lmneas segzn la BD a la que se quiera

 * acceder y la clase que se quiera utilizar para ello.

 */

require ("ConexionMySQL.inc");

$conexion = new ConexionMySQL();

 

?>

 

Para acceder a una base de datos, tan sólo tendremos que incluir este último fichero y acceder a las funciones de las BD a través de él, de esta forma:

 

<?php

      require ("CreaConexion.inc");

 

      $conexion->connect("localhost", "nobody");

      $conexion->select_db("prueba", $link);

 

      $asignaturas = $conexion->query("SELECT codigo, nombre, descripcion,

                                   creditos, tipo

                                   FROM asignatura");

?>

 


4. Características y funciones adicionales

Muchas características avanzadas de PHP, que en muchos casos en ASP vienen en paquetes a parte por los que hay que pagar más, se nos han quedado en el tintero. Algunos de estas características podrían no venir en la instalación por defecto de PHP, ser opcionales a la hora de compilar o incluso necesitar de paquetes a parte, por lo que podrían no estar disponibles en un sistema concreto.

 

4.1. Módulos disponibles

Los siguientes módulos y funciones están disponibles en la mayoría de instalaciones de PHP, y casi todos son gratuitos (algunos pueden depender de alguna librería propietaria):

 

http://www.php.net/manual/ref.exec.php

 

http://www.php.net/manual/ref.math.php

http://www.php.net/manual/ref.bc.php

 

http://www.php.net/manual/ref.datetime.php

http://www.php.net/manual/ref.calendar.php

http://www.php.net/manual/ref.mcal.php

 

http://www.php.net/manual/ref.image.php

 

http://www.mmlinux.net/manual-php/ref.pcre.html

http://www.mmlinux.net/manual-php/ref.regex.html

 

http://www.php.net/manual/ref.sem.php

 

http://www.php.net/manual/ref.com.php

 

http://www.php.net/manual/ref.domxml.php

http://www.php.net/manual/ref.xml.php

 

http://www.php.net/manual/ref.satellite.php

 

http://www.php.net/manual/ref.mcrypt.php

 

http://www.php.net/manual/ref.zlib.php

 

http://www.php.net/manual/ref.ftp.php

 

http://www.php.net/manual/ref.mail.php

 

http://www.php.net/manual/ref.imap.php

 

http://www.php.net/manual/ref.icap.php

 

http://www.php.net/manual/ref.ldap.php

 

http://www.php.net/manual/ref.gettext.php

 

http://www.php.net/manual/ref.pdf.php

 

http://www.php.net/manual/ref.swf.php

 

http://www.php.net/manual/ref.cybercash.php

http://www.php.net/manual/ref.pfpro.php

 

http://www.php.net/manual/ref.aspell.php

http://www.php.net/manual/ref.pspell.php

 

4.2. Productos de Zend

Zend, además del intérprete de PHP, es el nombre de una empresa fundada por los creadores de PHP para desarrollar mejoras y programas auxiliares (algunos de pago) para PHP. Los siguientes programas están ya disponibles o lo estarán a lo largo del año:

 

 

La dirección de Zend en Internet es:

 

          http://www.zend.com

 

Además de información sobre sus productos, tiene bastantes tutoriales y artículos sobre PHP.