Introducción a las funciones en PHP

Introducción

He considerado oportuno explicar desde las cosas más básicas y sencillas con respecto a las funciones hasta las más complejas, ya que nos pueden ahorrar inventarnos otros mecanismos más inadecuados si no conocemos las maravillosas características que se pueden tener un método o función bien construido. Empecemos pues por lo más fácil y vayamos aumentando el nivel...

Declarar una función simple:

desde PHP4 se pueden declarar antes y después del lugar donde es llamada.

<?php
   function imprimirNegrita($texto){
      echo "<b>$texto</b>";
   }
   echo "Linea sin negrita<br>";
  imprimirNegrita("Linea en negrita<br>");
?>

La sentencia return

En un punto de la función se encontrará en un estado final y dispuesta a devolverle el control a quien la llamó, por ejemplo cuando llega al final del bloque de código de la función, la ejecución coge entonces la línea siguiente de aquella donde fue llamada. Otra forma de para la ejecución de la función es usar la sentencia return. Seguramente existirán varias en una función, pero usar demasiados puede ser una barrera para comprender el flujo de la ejecución y hace más difícil la lectura del código. Lo ideal es tener una entrada y una salida pero en la práctica hay casos en los que es más que aceptable tener múltiples sentencias return.

<?php
  function hacerNegrita($texto){
    $texto = "<b>$texto</b>";
    return $texto;
  }
  echo "Linea sin negrita<br>";
  echo hacerNegrita("Linea en negrita<br>");
?>

Paso por referencia y por valor:

Para la mayor parte de los tipos de datos ,las variables pasadas como argumentos de la función se hacen por valor, en PHP4 se puede forzar a pasarlos por referencia mediante el uso de "&" justo antes del nombre de la variable: &$variable.

Las funciones también disponen de esta característica si realizamos algo como lo siguiente:

<?php
 function &obtenerMatrizAleatoria(){
   $matriz = array();
   for ( $i=0; $i<10; $i++ ){
      $a[] = rand(1,100);
   }

   return $a;
}
  $nuevaMatriz =&obtenerMatrizAleatoria();
?>

Sin embargo, hay que tener en cuenta que el uso de & estará "vetado" a partir de PHP6.x o superiores y si usamos la referencia con una sentencia new aparecerá un error de tipo STRICT a partir de la versión 5 de PHP.

<?php
  class MiClase {
    /** Constructor de MiClase */
    function MiClase(){}
  }
  $c =& new MiClase(); //Devuelve "deprecated" en PHP5.x+
?>

Ámbitos

El ámbito ,también llamado "scope", se creaó para evitar colisiones entre variables de diferentes funcione, PHP incluye dicha noción de ámbito. Cada línea de código pertenece a un determinado "scope". El código dentro de una función se considera que pertenece al ámbito de la propia función. El código fuera de la función pertenece al ámbito global del fichero. El ámbito es la propiedad que determina qué tabla de memoria se usa para almacenar las variables y alternativamente qué variables son accesibles.

Por lo tanto ,las variables de una función son locales a ésta,por lo que no se podrán modificar desde fuera de ella ya que son de propiedad privada. Sin embargo las variables globales fuera de la función han de declararse como globales accesibles por medio de la sentencia "global" antes del nombre de variable, ejemplo: "global $mivariable" es accesible en una función si realizamos dicho acceso de la variable declarada fuera:

  <?php
   $ciudad  = "Granada";
    function miCiudad(){
        global $ciudad;
         mostrarCiudad($ciudad);
    }

    function mostrarCiudad($nombre){
        echo "La ciudad seleccionada es :".$nombre."<br>";
    }

    function OtraCiudad(){
        $ciudad = "Sevilla";
        mostrarCiudad($ciudad);
    }

     miCiudad();
     OtraCiudad();
?>

Cuando se ejecuta el script se muestra Granada y Sevilla en ese orden. Aunque hayamos modificado $ciudad dentro de la función OtraCiudad() ,no es la misma que la del ámbito global.

La sentencia global lleva una variable a un espacio de nombres de una función,desde ese momento se puede modificar dentro o fuera de aquella. Así es posible referenciar la variable a través del array $_GLOBALS donde se indexan por el nombre, de forma que podríamos acceder a "global $ciudad" por medio de $_GLOBALS['ciudad'].

Variables estáticas

Recordemos que cuando creamos una variable dentro de una función sólo existe mientras la función se esté ejecutando. Una vez que la ejecución finalice y se pase el control al proceso que realizó la llamada, todo el espacio de variables para esa función es borrado, a veces esto no es lo deseable porque necesitamos que la función recuerde el último estado de las variables entre llamadas, esto se puede implementar por medio del uso de la sentencia "static".

En el comienzo de la función antes de los comandos debes declarar las variables que van a ser estáticas,entonces mantendrán su valor incluso después de abandonar la función. Veamos un ejemplo sencillo para usar esto (alternar colores de las celdas de una tabla):

<?php

    function alternarColor(){

        //Recordar Color usado

        static $color = "#00FF00";

        if ($color=="#00FF00"){

            $color = "#CCFFCC";

        } else {

            $color = "#00FF00";

        }

        return $color;

    }

    echo '<table>';

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

        $color = alternarColor();

        //Mostrar la fila en el color alternado:

        echo '<tr><td bgcolor="'.$color.'">Fila '.$i.'</td></tr>'."\n";

    }

    echo '</table>';

?>

Argumentos

Cuando se declara una función es posible que necesitemos usar argumentos dentro del paréntesis y separados por comas, si se usa el operador & se pasan por referencia (se pasa la dirección de memoria de la variable desde la llamada) y si no se especifica se pasan por valor (se hace una copia de la variable), los cambios realizados sólo permanecen después de salir de la función con el paso por referencia.

Un argumento puede tener un valor por defecto, esto se hace con una asignación (usando el "=" ) al especificar el nombre de variable dentro del paréntesis de la declaración de la función, ejemplo:

<?php

    function mostrarColor($texto, $color="black", &$cuenta=NULL){

        echo '<span style="color:'.$black.';">'.$texto.'</span>';

        //La funci&oacute;n isset() comprueba que $cuenta no tenga un valor NULL (nulo).

        if (isset($cuenta) && is_numeric($cuenta)) $cuenta = intval($cuenta)+1;

    }

    mostrarColor("Texto en negro").'<br>';

    mostrarColor("Texto en azul","blue").'<br>';

    //Ahora declaramos $c para pas&aacute;rsela como argumento a la funci&oacute;n:

    $c = 0;

    mostrarColor("Texto en rojo con cuenta","red",$c).'<br>';

    mostrarColor("Texto en verde con cuenta","green",$c).'<br>';

    echo "Cuenta total: $c <br>";

?>

La cuenta ha de tener 2 al final de la ejecución.

Funciones para recuperar propiedades de una función

Podemos acceder a los argumentos por su posición usando tres funciones:

func_get_arg($numero_argumento): el primer argumento tiene índice 0.

func_get_args(): el primer argumento también tiene índice 0.

func_num_args(): devuelve el número de argumentos de una función

Ejemplo para usar estas funciones:

<?php

    function crearLista(){

        echo "<ol>\n";

        $n = func_num_args();

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

            echo "<li>". func_get_arg($i)."</li>\n";

        }

        echo "</ol>\n";

        crearLista("GNU/Linux","Apache","MySQL","PHP","XML");

    }

?>

Para recuperar los nombres de las clases existe

get_class($variable_instancia_objeto)

que devuelve el nombre como una cadena.

Para obtener sus métodos en un array de los nombres de los métodos de la clase, usa

 get_class_methods($nombre_clase)

o la alternativa con el objeto:

get_class_methods($variable_instancia_objeto)

Para obtener las variables de una clase en un array , usa

get_class_vars($nombre_clase)

y la variante para el objeto instanciado es

get_object_vars($variable_instancia_objeto)

Además podemos recuperar el nombre del padre de la clase con

 get_parent_class($variable_instancia_objeto)

o bien con

 get_parent_class($nombre_clase). 

Quizás una útil función es

  is_a(object $instancia, string $clase)

que sirve para comprobar si una determinada variable $instancia de objeto es del tipo especificado en la cadena $clase.

De hecho, si la clase ha heredado de otra se pueden comprobar con

 is_subclass_of(object $instancia, string $nombre_clase)

Por último para comprobar si existe un método en la instancia de un objeto dado:

boolean method_exists(object $instancia, string $nombre_metodo)

Recursividad

¡Qué sería de las funciones sin la recursividad! . Nuestras funciones hacen llamadas a otras funciones y estas al mismo tiempo pueden hacer llamadas a si mismas. El proceso de una función que se llama a sí misma se llama Recursividad. Esta definición circular lleva a la elegancia del diseño de algoritmos, también se puede definir como la solución a un problema que se subdivide en subproblemas más pequeños varias veces. Son muy comunes en Matemáticas, ejemplo: la serie de Fibonacci. En zenphp podemos encontrar funciones implementadas que usan esta técnica (Ver). A veces puede resultar complejo comprender un algoritmo recursivo y nos lleva un tiempo realizar la traza de la ejecución. Se suele utilizar por motivos de eficiencia, ya que 10 llamadas en PHP necesita mantener 10 copias es necesario que nos ocupemos manualmente de las variables...

Ejemplo de uso de la recursión en una función:

<?php

    function comprobarEntero($numero){

        if ($numero > 1 ){

        return comprobarEntero($numero-1);

    } elseif ($numero < 0){

        return comprobarEntero((-1)*$numero-1);

    } else {

        if ($numero > 0  &&  $numero < 1) return "No";

        else return "Si";

    }

}

echo "Es 0 un entero?".comprobarEntero(0)."<br>";

echo "Es 7 un entero?".comprobarEntero(7)."<br>";

echo "Es 2.7 un entero?".comprobarEntero(2.7)."<br>";

echo "Es -7 un entero?".comprobarEntero(-7)."<br>";

?>

Llamadas dinámicas a funciones

Puede que no sepas qué función llamar cuando estás escribiendo un script de PHP, posiblemente sea porque los datos en los que te bases determinen qué hacer durante la ejecución, una forma de llevar esto a cabo es establecer una variable con el nombre de una función y después usarla como si fuera una función. Si a una variable le sigue un paréntesis se interpreta de esta forma, se tratará como una función, veamos un ejemplo:

<?php

    function mostrar($texto)

    {

        echo $texto;

    }

    function mostrarNegrita($texto){

        echo '<b>'.$texto.'</b>';

    }

    $miFuncion = 'mostrar';

    $miFuncion("Hola!").'<br>';

    $miFuncion = 'mostrarNegrita';

    $miFuncion("Hola en negrita!").'<br>';

?>

Si no sabes exactamente como funcionará exactamente puedes crear una función anónima por medio de la función "create_function".

Funciones definidas por el usuario

La función "create_function" crea una función y devuelve un nombre único, por eso son funciones anónimas, eso permite escribir funciones que dependen de información sólo disponible en tiempo de ejecución, aunque puedes almacenar el nombre de esta nueva función en una variable para lalmarla después, create_function es quizás el método más útil para definir funciones de tipo lambda, ejemplo:

<?php

    $datos  = array("zanahoria","manzana","naranja");

    //añade subrayado bajo al final de cada palabra y convertir todo a mayúsculas:

    array_walk($datos, create_function('&$v','$v = "_".strtoupper($v)."_";'));

    print_r($datos);

?>

Puedes crear y usar tus propias funciones con "call_user_func($nombre_funcion,...)", ejecuta una función definida por el usuario, donde "..." a continuación son los argumentos a pasar a dicha función en tiempo de ejecución. Puedes usarla para llamar a un método de un objeto ,entonces en lugar de un nombre usa un array donde el primer argumento es el objeto donde reside el método y el segundo el nombre de la función,ahi termina el array, el resto igual que antes...

call_user_func_array($funcion, $array_de_parametros ) 

es igual que call_user_func excepto porque hay un array de parámetros en lugar de varios argumentos.

Un método no recomendado es eval(), intenta ejecutar el argumento pasado, que es código PHP, ejemplo:

<?php

    $codigo = '<b><?php print(date("d-m-Y"));?></b>';

    eval ("?>".$codigo);

?>

Más ejemplos en blog.zenphp.es ;)

Resumen

Repaso al uso de funciones en PHP, desde los aspectos más básicos (declaración de funciones simples) hasta la realización de operaciones más complejas (uso de recursividad y llamadas dinámicas a funciones) .

Índice

  1. Funciones en PHP

Otros artículos