Desarrollo

Variables locales y globales en PHP

Desarrollo PHP

Retomamos el tema de las funciones ampliando funcionalidades, explicando capacidades y aspectos que debemos ir teniendo en cuenta. Como, por ejemplo, el tema que nos ocupa hoy: las variables locales y globales. Visita el índice de contenidos si quieres ver todo lo publicado sobre funciones antes de continuar.

Un primer ejemplo

Antes de explicar a qué nos estamos refiriendo con ésto de las variables locales y globales, vamos a ver un pequeño ejemplo para ver qué sucede.

<?php
$numero = 1234;

function imprimir_numero() {
  echo $numero;
}

imprimir_numero();
?>

Simplemente queremos que cada vez que queramos imprimir ese número, llamemos a esa función y listo. Fácil, ¿verdad? Ejecutemos este programa y veamos cómo imprime el 1234 por pantalla…

Notice: Undefined variable: numero in C:\xampp\htdocs\globales.php on line 5

¿Cómo? ¿Variable no definida? No es posible, ¡pero si la hemos definido nada más comenzar!

En primer lugar, quizá si probáis algunos de vosotros veréis que no imprime absolutamente nada. Ésto será debido a que no tenéis activo el modo de depuración que os muestra errores y avisos. Simplemente, como esa variable no está definida (es null), no puede imprimirla. ¿Pero por qué?

Ámbito de las variables

El ámbito de las variables es el contexto dentro del cual esa variable está definida. Dentro de una función existe un ámbito local a la función, con lo cual todas las variables que se utilicen allí dentro se encuentran limitadas al ámbito local de la propia función. ¿Recordáis aquel artículo de A practicar… donde dijimos que debíamos devolver el valor de $agenda_diaria con un return o no nos funcionaría? Aquí tenemos la razón.

Variables locales y globales

La variable $numero es una variable definida en el ámbito global. Digamos que está definida en el ámbito más externo de nuestro programa, con lo que está disponible en cualquier lado. Pero con matices.

En el momento en el que entremos dentro de una función, las variables allí definidas y utilizadas van a tratarse como variables locales y, por tanto, no podremos acceder a ellas desde fuera de la función, ni tampoco podremos acceder a variables que se han definido fuera de la función para utilizarlas aquí. En el artículo que comentábamos, recordad que la variable $agenda_diaria la devolvíamos dentro de la función con un return, pero también la pasábamos como argumento porque la función no puede utilizar la de fuera. Al menos, sin hacer algo antes.

En último lugar, hay que diferenciar entre lenguajes de programación. Hay algunos lenguajes que utilizan las variables globales de otra forma y, por definición, se pueden utilizar en cualquier punto del programa, dentro de las funciones incluidas. Para ello siempre debemos mirar la documentación oficial.

La palabra clave global

Dentro de nuestras funciones podemos indicarle que vamos a utilizar una variable global. Para ello, utilizamos la palabra clave global antes de la variable, normalmente al principio de la función. Con ello, estamos diciéndole a la función que utilice esa variable que ha sido definida fuera de la propia función. Veamos el ejemplo anterior con esta nueva definición:

<?php
$numero = 1234;

function imprimir_numero() {
	global $numero;

	echo $numero;
}

imprimir_numero();
?>

En la línea 5 hemos añadido esa nueva línea de código para indicar que $numero en realidad es una variable global. Ahora, si ejecutamos este programa, veremos por pantalla el 1234 esperado. Nuestra función está cogiendo el valor global de $numero.

¿Y por qué no por argumentos?

Debido a que lo que recibimos como argumentos son una copia de las variables para “transformarlas” en variables locales de la función. Vamos a crear otro pequeño programa con una función para obtener el valor doble de un número.

<?php
$numero = 1234;

function obtener_el_doble($numero) {
	$numero = $numero * 2;
}

obtener_el_doble($numero);
echo $numero;
?>

Probemos este programa. ¿Qué se imprime por pantalla? Podríamos esperar que se imprimiera un 2468, es decir, el doble de 1234. Pero no, por pantalla vemos un 1234.

Una pequeña traza

¿No ha hecho nada nuestra función? Vamos a utilizar var_dump para hacer una pequeña traza. Primero, nuestro programa con var_dump:

<?php
$numero = 1234;

function obtener_el_doble($numero) {
	echo 'Estamos dentro de la función<br>';
	var_dump($numero); echo '<br>';
	$numero = $numero * 2;
	var_dump($numero); echo '<br>';
}

echo 'Estamos fuera de la función<br>';
var_dump($numero); echo '<br>';
obtener_el_doble($numero);
echo 'Estamos fuera de la función de nuevo<br>';
var_dump($numero); echo '<br>';
echo $numero;
?>

Hemos colocado unos cuantos echo y var_dump para ver qué va ocurriendo en nuestro programa (para este ejemplo tan sencillo, incluso no hubiéramos tenido que necesitar var_dump). Ejecutamos y obtenemos lo siguiente:

Estamos fuera de la función
int(1234)
Estamos dentro de la función
int(1234)
int(2468)
Estamos fuera de la función de nuevo
int(1234)
1234

Primero ha llegado a la línea 11 donde se imprimía “Estamos fuera de la función” para, a continuación, mostrar el valor de $numero en ese momento, que es 1234. Luego entramos en la función obtener_el_doble y dentro de la función vemos que imprime un 1234 al principio y luego el 2468 una vez realiza la multiplicación. Pero, finalmente, volvemos a ver que estamos ya fuera de la función y se imprime un 1234 en nuestra variable $numero. Algo ha pasado ahí y las variables locales y globales tienen la clave.

El valor de un argumento es, en realidad, una copia

Como ya dijimos en su momento como avance, en realidad el valor que obtiene la función es una copia que se trata como una variable local. Por tanto, es como si existieran dos versiones de la variable $numero y, dentro de la función, modificamos una, pero fuera de la función no lo hacemos. Por ello, en el artículo que comentábamos, acabábamos devolviendo la variable, pues realmente “era otra distinta”.

Utilizando la variable global

Pese a que hay otras formas (pasar valores por referencia), no son objeto de este artículo. Vamos a volver a escribir este ejemplo indicándole el valor como global esta vez.

<?php
$numero = 1234;

function obtener_el_doble() {
	global $numero;
	
	$numero = $numero * 2;
}

obtener_el_doble();
echo $numero;
?>

Ahora no hemos pasado $numero a la función, sino que dentro de ella indicamos que $numero es una variable global. Probamos a ejecutar este código y, ahora sí, vemos por pantalla el 2468 que esperábamos.

El array $GLOBALS

Tenemos otra forma de acceder a las variables locales, que es con el uso del array predefinido $GLOBALS. En él se guardan todos los contenidos de las variables y se utiliza, como índice de cada elemento, el nombre de la variable. Por ejemplo, el programa anterior lo podríamos haber escrito así:

<?php
$numero = 1234;

function obtener_el_doble() {
	$GLOBALS['numero'] = $GLOBALS['numero'] * 2;
}

obtener_el_doble();
echo $numero;
?>

En lugar de utilizar $numero dentro de la función, estamos utilizando su equivalente $GLOBALS[‘numero’] y hará exactamente lo mismo. De esta forma no necesitamos indicar en la función qué variable es global (incluso podríamos tener otra variable $numero que fuera distinta, al ser local, pero ésto sólo haría que liarnos como programadores). Dependerá entonces del programador qué tipo utilizar. Si vamos a utilizar mucho esta variable, quizá es más cómodo indicarla como global y utilizarla de forma normal, pero ya es a gusto personal de cada uno.

¿Y al revés?

Alguno se puede estar preguntando: ¿y utilizar una variable definida dentro de una función fuera de la propia función? Sí, se puede, pero será objeto de otro artículo cuando veamos las variables estáticas.

Cuidado siempre con el ámbito de las variables

Cuando empecemos a hacer programas más grandes, extensos y llenos de funciones, hay que tener cuidado con el ámbito de las variables y controlar muy bien las variables locales y globales. Si nos liamos, es posible que no estemos cogiendo los datos correctos, utilizando algunos datos no procesados o al revés, hacer algunas operaciones con variables que luego, al acabar las funciones, se pierden.

Es conveniente, especialmente cuando estamos iniciándonos en la programación, el utilizar la sentencia return de las funciones y el que dentro de las funciones no hagamos más modificaciones que las necesarias para obtener una variable de retorno. Empezar a pensar en variables locales y globales puede llevarnos a errores, aunque saber usarlas ayuda a mejorar la eficiencia de nuestros programas.

Veremos este tipo de cosas en el próximo artículo en donde hablaremos de las funciones recursivas y utilizaremos varios ejemplos para ellas.

Deja una respuesta