PHP-TUT-07 Funciones de usuario

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

A lo largo de lo que hemos estudiado hasta el momento, hemos visto que PHP incorpora una serie de funciones. Son instrucciones que aparecen seguidas de un paréntesis en el que pueden recibir o no algún argumento, y que pueden devolver o no algún valor. En artículos anteriores conocimos algunas como, por ejemplo, settype(). Lo cierto es que PHP incorpora muchísimas funciones para distintos cometidos. En los próximos artículos iremos descubriendo que son más de lo que ahora imaginas, y que resuelven muchas situaciones.

Pero, en ocasiones, se nos presenta la necesidad de recurrir a funciones que no están implementadas en el lenguaje. Dada la naturaleza open source de PHP, puedes descargar de Internet (http://www.php.net) el código fuente del intérprete, modificarlo para adaptarlo a tus necesidades y volver a compilarlo… si eres un avezado programador con cientos de horas de experiencia, claro. La mayoría de nosotros, sin embargo, no nos atrevemos a meter las manos en un pastel de esa envergadura. Afortunadamente PHP nos proporciona una solución válida para esas situaciones. Si necesitamos una función que no forme parte del lenguaje podemos definirla en nuestro script, con los conocimientos que ya tenemos y los que vamos a adquirir a lo largo de los artículos de esta serie. Para ello, usamos la instrucción function (), que permite definir una función con el código que nosotros deseemos y ejecutarla, cuando sea necesario, con una simple llamada. Dentro de la función pondremos las instrucciones que sean necesarias para que haga lo que nosotros queremos. Estas instrucciones constituyen el cuerpo de la función. La definición de una función responde al siguiente esquema genérico:

function nombreDeLaFuncion (arg1, arg2,…, argn) {
    //cuerpo de la función
}

Al definir la función, se establece su nombre y, a través de él, se la podrá invocar en cualquier parte del script que sea necesaria. Los argumentos arg1, arg2, etc., son opcionales. Se emplearán o no, dependiendo de que la función los necesite para hacer aquello para lo que haya sido creada. Veamos un código de ejemplo muy simple para ir asentando ideas. Es el script funcionNoEjecutada.php:

Carga el script en el navegador. Verás que, simplemente, no aparece nada en la página. La línea que tenía que mostrar “Número 2” no lo muestra. Esto es porque, cuando se define una función, esta se carga en memoria, pero su contenido no se ejecuta hasta que dicha función es invocada por su nombre, como si ese nombre fuera una instrucción más de PHP. Modifiquemos el código para invocar la función, tal como se ve en el script funcionEjecutada.php:

Observa cómo hemos invocado la función, en la línea que aparece justo después de la misma. Cuando cargues este script verás como sí se ejecuta el cuerpo de la función. Un detalle curioso acerca de las funciones es que, excepcionalmente, el nombre de éstas no es sensible a mayúsculas y minúsculas, de forma que el listado anterior habría funcionado igual si la función la invocamos así: mostrarunnumero();. De todas formas esta es una licencia que yo desaconsejo encarecidamente, pues es muy posible que en futuras versiones del intérprete esto cambie.

PASANDO ARGUMENTOS

A las funciones se les pueden pasar argumentos para adaptar su operativa a cada caso. En realidad esto no es del todo nuevo. Ya lo hemos visto hacer con algunas de las funciones propias del lenguaje. Cuando, por ejemplo, invocamos a gettype ($dato) para recuperar el tipo de valor contenido en una variable, el nombre de esa variable, colocado entre los paréntesis, constituye el argumento, o parámetro que le pasamos a la función. Cuando se trata de nuestras propias funciones, el sistema es el mismo. Debemos invocar a la función pasándole el argumento (o los argumentos, puede requerir más de uno) entre paréntesis. Pero además, al definir la función, es necesario especificar qué argumentos debe recibir. Mira el script funcionConArgumento.php:

Ejecuta el script. Verás que muestra en la página el número 3. Observa cómo hemos definido la función y cómo la hemos invocado. En la invocación hay un argumento que es la variable $numero. Cuando se efectúa esta llamada a la función esta variable se aloja, dentro de la función, en la variable $mostrar, que aparece en la definición. Dentro del cuerpo de la función ves cómo tomamos la variable $mostrar, que ha recibido el valor de $numero.

Siempre debe haber el mismo número de argumentos en la definición de una función que en la invocación a la misma, y éstos aparecerán separados por comas. Observa el script funcionDosArgumentos.php:

Observa las líneas resaltadas para comprobar cómo se definen e invocan funciones que usan más de un argumento.

Sin embargo, desde la versión 4 de PHP es posible pasarle a una función un número mayor de argumentos de los que está diseñada para recibir. Los argumentos, en este caso, se gestionarán mediante tres funciones que PHP implementa al efecto. Son func_num_args (), func_get_arg () y func_get_args (). La primera devuelve el número total de argumentos pasados a nuestra función. La segunda recibe un número y devuelve ese argumento, y la tercera devuelve todos los argumentos en una matriz indexada. Para comprender la operativa de estas funciones veamos el script manejoDeArgumentos.php:

Ejecuta el script y analiza el resultado para ver cómo se corresponde con el uso de cada una de estas funciones. De este modo, podemos usar estos argumentos aunque no se hayan declarado en la definición de la función. Es importante aclarar que estas tres funciones han sido creadas para ser usadas dentro de las funciones que defina el usuario. Si intentas usarlas en el cuerpo general del script, fuera de una función, se producirá un error con un mensaje como el siguiente:

Warning: func_num_args(): Called from the global scope - no function context in C:\Documents and Settings\Jose\Mis documentos\Mis webs dinamicas\capitulo_04\listado.php on line 23

(Nota: El mensaje exacto puede variar, dependiendo de la versión de PHP que tengas instalada, pero su sentido será el mismo).

Cuando se le pasan argumentos a una función, éstos se pueden pasar por valor o por referencia. Veamos qué es esto y cómo funciona. Para ello fíjese en el script pasoPorValor.php:

 

Observa el resultado que obtienes al ejecutar el script. Fíjate en que tenemos una variable llamada $numero que se declara fuera de la función, asignándole el valor 3. Esta variable se pasará como argumento a la función y, en la definición de la misma, aparece también la variable $numero. Sin embargo, aunque tiene el mismo nombre, no es la misma variable. La que aparece en la definición de la función pertenece, exclusivamente, a la función, mientras que la que aparece fuera de la función pertenece a todo el script. Para entender esto debemos analizar lo que ocurre cuando cargamos el script en el navegador:

En primer lugar se ejecuta la línea:

$numero = 3;

Como ya sabemos, la función se ha cargado en memoria, pero no será ejecutada mientras no se invoque. A continuación, se ejecuta la siguiente línea:

echo "El número, antes de invocar la función vale: ".$numero."<br />";

Esto nos muestra en la página el valor de la variable.

Ahora se invoca la función, mediante la línea:

cuadrado($numero);

Dentro de la función, el valor de $numero se eleva al cuadrado (se multiplica por sí mismo). Esto ocurre en la línea:

$numero *= $numero;

Entonces se muestra el valor que adquiere dentro de la función, así:

echo "En la función el número se eleva al cuadrado, obteniendo el resultado: ".$numero."<br />";

Corresponde a la segunda línea de resultados que aparece en la página.

Cuando termina la función, continúa la ejecución del script, con la línea:

echo "El número, después de invocar la función vale: ".$numero;

Entonces se muestra la tercera línea de resultados en la página.

De lo que quiero que te des cuenta es de que el valor de la variable, que al inicio del script es de 3, sigue inmutable al final del script, independientemente de lo que haya ocurrido en la función. Esto es así porque, cuando se invoca la función no se le pasa la variable del argumento, sino sólo su valor. Es decir, al invocar la función tal como hacemos aquí, no le pasamos como argumento la variable $numero, sino el valor 3 (o el que tuviera en ese momento). Por esta razón, la función no opera con la variable $numero del script, sino con el valor 3. Esto es lo que se llama paso de argumentos por valor.

Como contraparte está el paso de argumentos por referencia, en el que sí se pasa la variable original y se opera con ella, de modo que todo lo que hagamos en la función afectará a dicha variable original. Para indicar que un argumento se va a pasar por referencia se le antepone el signo & en la definición de la función. Mira un ejemplo en el script pasoPorReferencia.php:

Fíjate en la línea resaltada para ver cómo se hace que un argumento pase por referencia. Ahora observa el resultado en tu navegador.

La diferencia está en la tercera línea de resultados que aparece en la página. Como ves, esta vez la variable, vista desde fuera de la función, sí ha sido alterada por lo que ha ocurrido dentro de la función.

Cada vez que invoques la función que ha sido definida de este modo, el argumento se pasará por referencia. También puede ocurrir que necesites, llegado el caso, crear una función en la que los argumentos sean pasados por valor, pero en alguna invocación concreta del script deba pasarlos por referencia. En ese caso, define la función normalmente, así:

function miFuncion ($arg1, $arg2, $arg3){
    cuerpo de la function;
}

Cuando necesites pasar argumentos por valor (la mayoría de las veces es así) invócala normalmente, como se ve a continuación:

miFuncion ($arg1, $arg2, $arg3);

Pero ahora supongamos que necesitas hacer una llamada pasando los argumentos $arg2 y $arg3 por referencia. No es necesario que redefinas la función. Bastará con que la llames así:

miFuncion ($arg1, &$arg2, &$arg3);

RETORNO DE UNA FUNCIÓN

En muchas ocasiones las necesidades operativas de nuestros scripts requieren que una función devuelva un valor. Esto se consigue mediante la instrucción return seguida de la variable que contiene dicho valor. Para entender cómo opera esto veamos un ejemplo en el script funcionConResultado.php:

Ejecuta el script para ver cómo funciona y examina el código. Fíjate en el uso de la instrucción return. Es la que devuelve un dato a la instrucción que invocó a la función. En este caso, esta instrucción es una asignación, como puede ver. La instrucción return sólo permite “sacar” un valor de la función. Es decir, esta instrucción no puede ir seguida por más de un nombre de variable. Si, en algún momento, necesitas que la función devuelva al script más de un valor, lo que harás será crear una matriz, dentro del cuerpo de la función, con los valores que necesites, y hacer que la instrucción return vaya seguida por el nombre de esa matriz.

También puedes poner la instrucción return sin ninguna variable a continuación. Esto ocasiona que se interrumpa la ejecución de la función y se continúe la ejecución del script, sin devolver nada. Sin embargo, ésta es una solución que pocas veces necesitarás. Normalmente, este uso de return está supeditado a un condicional, de tal modo que si se cumple una condición determinada deba abandonarse la función.

ÁMBITO DE LAS VARIABLES

Cuando una variable se crea dentro del cuerpo de una función sólo existe dentro de esa función, no en el cuerpo principal del programa. Vamos a ver ahora cómo funciona esto, en datosEnFunciones.php.

Lo que nos interesa es lo siguiente: dentro de la función se ha declarado la variable $cuadrado. Esta variable almacena un resultado que se muestra mediante la instrucción echo que forma parte del cuerpo de la función. Cuando se termina la ejecución de la función se continúa con el script. Vemos que hay una línea destinada a mostrar el valor de $cuadrado y su tipo. Y no nos muestra ningún valor, y como tipo nos muestra NULL. Es decir, la variable no existe. Y, sin embargo, ha sido declarada y utilizada dentro del cuerpo de la función, que acaba de ejecutarse. Lo que vemos con esto es que una variable que se declara dentro de una función no existe fuera de la misma. Es una variable local, es decir, de ámbito privado de esa función. Por el contrario, una variable global, declarada en el cuerpo principal del script, está disponible para todo el script… excepto para las funciones, tal como muestra el script ambito.php:

Como puedes ver cuando lo ejecutas, la variable creada en el cuerpo del script no es visible desde dentro de la función. Por esto es que, cuando necesitamos pasar datos del script a la función, usamos los argumentos y, cuando necesitamos pasar un resultado desde la función al cuerpo del script, usamos la instrucción return.

Si queremos usar una variable global dentro del cuerpo de una función, la declararemos con la sentencia global, dentro de la función. De este modo, el intérprete “sabe” que esta variable también está disponible dentro de la función. Observa el script variablesGlobales.php, que es una variante del anterior.

 

Como ves, la variable $numero ha sido declarada como global dentro del cuerpo de la función. Eso hace que esté disponible tanto para dicha función como para el resto del código del script. Cuando una variable es de ámbito global puede ser llamada mediante una matriz específica de PHP. Se trata de $GLOBALS. Esta matriz es propia del intérprete, es decir, no es necesario declararla, y almacena todas las variables globales que se usan en el script. Cada vez que usted ejecuta un script, esta matriz se crea automáticamente. Se trata de una matriz asociativa en la que se crea un elemento por cada variable global que usa el script. El índice de cada elemento es el nombre de la variable y el contenido es el valor de esa variable. Usted puede usar esta matriz, como ve en el script matrizDeGlobales.php:

Observa el uso de la matriz $GLOBALS.

VARIABLES ESTÁTICAS

Las variables empleadas en las funciones tienen una característica. Si la función es invocada más de una vez durante la ejecución del script, las variables locales de la función no conservan su valor de una llamada a otra. Para ver claro a qué nos referimos observe el script estaticas.php:

Observe el cuerpo de la función. En la primera línea, se declara una variable y se le añaden cinco unidades. Como dicha variable no existe previamente, y estamos haciendo con ella una operación aritmética, PHP sobreentiende que es una variable numérica y le asigna, inicialmente, el valor cero. Al incrementarla en cinco unidades pasa a tener el valor cinco, tal como se muestra en la segunda línea. Después se multiplica por dos, con lo que pasa a valer diez, tal como se muestra en la cuarta línea. Fíjate en que se invoca dos veces a la función y en ambas ocasiones el resultado es el mismo. Esto quiere decir que el valor de la variable local $variableNormal se pierde al terminar la ejecución de la función. No se conserva de una ejecución a otra. Este es el funcionamiento normal, y realmente será el que necesitemos en la mayoría de los casos. Pero también puede ser que necesitemos que una variable local conserve su contenido de una ejecución de la función a otra. Para ello usamos la instrucción static. Observa el script usoDeEstaticas.php:

Ahora observa el resultado. La primera vez que se llama a la función, como $variableNormal no existe, PHP la crea y, cuando se le dice que la incremente en cinco unidades, le queda el valor cinco. Al multiplicarla por dos, le queda el valor diez. Como la variable ha sido declarada como estática, este valor se conserva, de modo que, al llamar a la función por segunda vez, cuando se incrementa en cinco unidades, queda con el valor quince. Al multiplicarla por dos, se le asigna el valor treinta.

RECURSIVIDAD

Un uso especial de las funciones definidas por el usuario es el que se conoce como recursividad, o uso recursivo. Consiste en que dentro del cuerpo de la función se vuelve a invocar a dicha función, con lo que se inicia otra ejecución de la misma, y así sucesivamente. La verdad es que es un recurso poco utilizado pero, por ejemplo, nos va a venir bien para calcular el factorial de un número. Como ya sabes, esta operación consiste en multiplicar un número por todos los que hay menores que él, excepto el 1 y el 0. El factorial de 5 será 5*4*3*2=120. Observa el script recursivas.php:

Ejecuta el script para ver su funcionamiento. Observa como la función se llama a sí misma. Ten cuidado de prever una salida de la función (en nuestro ejemplo es cuando el número llega a 0), o entrarás en un bucle infinito que bloqueará tu navegador.

     

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *