¿Qué es el "alcance variable"?
Las variables tienen un "alcance" o "lugares desde los cuales son accesibles". El hecho de que haya escrito $foo = 'bar';
una vez en algún lugar de su aplicación no significa que pueda hacer referencia $foo
desde cualquier otro lugar dentro de la aplicación. La variable $foo
tiene un cierto alcance dentro del cual es válida y solo el código del mismo alcance tiene acceso a la variable.
¿Cómo se define un alcance en PHP?
Muy simple: PHP tiene alcance de función . Ese es el único tipo de separador de alcance que existe en PHP. Las variables dentro de una función solo están disponibles dentro de esa función. Las variables fuera de las funciones están disponibles en cualquier lugar fuera de las funciones, pero no dentro de ninguna función. Esto significa que hay un alcance especial en PHP: el alcance global . Cualquier variable declarada fuera de cualquier función está dentro de este alcance global.
Ejemplo:
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
}
$foo
está en el ámbito global , $baz
está en un ámbito local dentro myFunc
. Solo el código interno myFunc
tiene acceso a $baz
. Solo el código externo myFunc
tiene acceso a $foo
. Ninguno tiene acceso al otro:
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
echo $foo; // doesn't work
echo $baz; // works
}
echo $foo; // works
echo $baz; // doesn't work
Alcance y archivos incluidos
Los límites del archivo no separan el alcance:
a.php
<?php
$foo = 'bar';
b.php
<?php
include 'a.php';
echo $foo; // works!
Se aplican las mismas reglas al include
código d que a cualquier otro código: solo function
el alcance separado. Para fines de alcance, puede pensar en incluir archivos como copiar y pegar código:
c.php
<?php
function myFunc() {
include 'a.php';
echo $foo; // works
}
myFunc();
echo $foo; // doesn't work!
En el ejemplo anterior, a.php
se incluyó dentro myFunc
, cualquier variable dentro a.php
solo tiene un alcance de función local. El hecho de que parezcan estar en el ámbito global a.php
no significa necesariamente que lo estén, sino que depende del contexto en el que se incluye / ejecuta ese código.
¿Qué pasa con las funciones dentro de las funciones y clases?
Cada nueva function
declaración introduce un nuevo alcance, es así de simple.
(anónimo) funciones dentro de funciones
function foo() {
$foo = 'bar';
$bar = function () {
// no access to $foo
$baz = 'baz';
};
// no access to $baz
}
clases
$foo = 'foo';
class Bar {
public function baz() {
// no access to $foo
$baz = 'baz';
}
}
// no access to $baz
¿Para qué sirve el alcance?
Tratar los problemas de alcance puede parecer molesto, ¡pero el alcance variable limitado es esencial para escribir aplicaciones complejas! Si cada variable que declara estaría disponible desde cualquier otro lugar dentro de su aplicación, estaría pasando por encima de sus variables sin una forma real de rastrear qué cambia qué. Hay pocos nombres razonables que puede dar a sus variables, probablemente quiera usar la variable " $name
" en más de un lugar. Si solo pudiera tener este nombre de variable único una vez en su aplicación, tendría que recurrir a esquemas de nombres realmente complicados para asegurarse de que sus variables sean únicas y que no esté cambiando la variable incorrecta del código incorrecto.
Observar:
function foo() {
echo $bar;
}
Si no hubiera alcance, ¿qué haría la función anterior? De donde $bar
viene ¿Qué estado tiene? ¿Es incluso inicializado? ¿Tienes que revisar cada vez? Esto no es mantenible. Lo que nos lleva a ...
Cruzando los límites del alcance
La forma correcta: pasar variables dentro y fuera
function foo($bar) {
echo $bar;
return 42;
}
La variable $bar
entra explícitamente en este ámbito como argumento de función. Con solo mirar esta función, queda claro de dónde provienen los valores con los que trabaja. Luego, devuelve explícitamente un valor. La persona que llama tiene la confianza de saber con qué variables trabajará la función y de dónde provienen sus valores de retorno:
$baz = 'baz';
$blarg = foo($baz);
Extender el alcance de las variables a funciones anónimas.
$foo = 'bar';
$baz = function () use ($foo) {
echo $foo;
};
$baz();
La función anónima incluye explícitamente $foo
desde su alcance circundante. Tenga en cuenta que esto no es lo mismo que el alcance global .
La forma incorrecta: global
Como se dijo antes, el alcance global es algo especial, y las funciones pueden importar explícitamente variables de él:
$foo = 'bar';
function baz() {
global $foo;
echo $foo;
$foo = 'baz';
}
Esta función usa y modifica la variable global $foo
. ¡No hagas esto! (A menos que realmente realmente realmente sepas lo que estás haciendo, e incluso entonces: ¡no!)
Todo lo que ve la persona que llama de esta función es esto:
baz(); // outputs "bar"
unset($foo);
baz(); // no output, WTF?!
baz(); // outputs "baz", WTF?!?!!
No hay indicios de que esta función tenga efectos secundarios , pero sí. Esto se convierte fácilmente en un lío enredado ya que algunas funciones se siguen modificando y requieren un estado global. Desea que las funciones no tengan estado , que actúen solo en sus entradas y que devuelvan salidas definidas, por muchas veces que las llame.
Debe evitar utilizar el alcance global de la forma más amplia posible; sin duda no debería "sacar" las variables del ámbito global a un ámbito local.