O que é "escopo variável"?
As variáveis têm um "escopo" limitado ou "locais de onde são acessíveis". Só porque você escreveu $foo = 'bar';
uma vez em algum lugar do seu aplicativo não significa que você pode se referir $foo
de qualquer outro lugar dentro do aplicativo. A variável $foo
tem um determinado escopo dentro do qual é válida e apenas o código no mesmo escopo tem acesso à variável.
Como um escopo é definido no PHP?
Muito simples: o PHP tem escopo de função . Esse é o único tipo de separador de escopo que existe no PHP. Variáveis dentro de uma função estão disponíveis apenas dentro dessa função. Variáveis fora das funções estão disponíveis em qualquer lugar fora das funções, mas não dentro de nenhuma função. Isso significa que há um escopo especial no PHP: o escopo global . Qualquer variável declarada fora de qualquer função está dentro desse escopo global.
Exemplo:
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
}
$foo
está no escopo global , $baz
está dentro de um escopo localmyFunc
. Somente o código interno myFunc
tem acesso $baz
. Somente o código externo myFunc
tem acesso $foo
. Nenhum dos dois tem acesso ao outro:
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
echo $foo; // doesn't work
echo $baz; // works
}
echo $foo; // works
echo $baz; // doesn't work
Escopo e arquivos incluídos
Os limites do arquivo não separam o escopo:
a.php
<?php
$foo = 'bar';
b.php
<?php
include 'a.php';
echo $foo; // works!
As mesmas regras se aplicam ao include
código d e a qualquer outro código: somente function
s escopo separado. Para fins de escopo, você pode incluir arquivos como código de copiar e colar:
c.php
<?php
function myFunc() {
include 'a.php';
echo $foo; // works
}
myFunc();
echo $foo; // doesn't work!
No exemplo acima, a.php
foi incluída dentro myFunc
, quaisquer variáveis dentro a.php
somente têm escopo de função local. Só porque eles parecem estar no escopo global a.php
não significa necessariamente que estão, na verdade depende do contexto em que o código é incluído / executado.
E as funções dentro de funções e classes?
Toda nova function
declaração introduz um novo escopo, é simples assim.
funções (anônimas) dentro de funções
function foo() {
$foo = 'bar';
$bar = function () {
// no access to $foo
$baz = 'baz';
};
// no access to $baz
}
Aulas
$foo = 'foo';
class Bar {
public function baz() {
// no access to $foo
$baz = 'baz';
}
}
// no access to $baz
Para que serve o escopo?
Lidar com problemas de escopo pode parecer irritante, mas o escopo variável limitado é essencial para escrever aplicativos complexos! Se todas as variáveis declaradas estivessem disponíveis em qualquer outro lugar dentro do aplicativo, você passaria por todas as variáveis sem uma maneira real de rastrear o que muda o quê. Existem apenas tantos nomes sensíveis que você pode atribuir às suas variáveis. Você provavelmente deseja usar a variável " $name
" em mais de um local. Se você pudesse ter esse nome de variável exclusivo apenas uma vez no aplicativo, seria necessário recorrer a esquemas de nomeação realmente complicados para garantir que suas variáveis sejam únicas e que você não esteja alterando a variável errada pelo código errado.
Observar:
function foo() {
echo $bar;
}
Se não houvesse escopo, o que a função acima faria? De onde $bar
vem? Que estado tem? É mesmo inicializado? Você tem que verificar todas as vezes? Isso não é sustentável. O que nos leva a ...
Cruzando limites do escopo
O caminho certo: passando variáveis dentro e fora
function foo($bar) {
echo $bar;
return 42;
}
A variável $bar
está entrando explicitamente nesse escopo como argumento de função. Apenas olhando para esta função, fica claro de onde os valores com os quais trabalha se originam. Em seguida, ele retorna explicitamente um valor. O chamador tem confiança para saber com quais variáveis a função trabalhará e de onde vêm seus valores de retorno:
$baz = 'baz';
$blarg = foo($baz);
Estendendo o escopo das variáveis para funções anônimas
$foo = 'bar';
$baz = function () use ($foo) {
echo $foo;
};
$baz();
A função anônima inclui explicitamente $foo
do seu escopo circundante. Observe que isso não é o mesmo que escopo global .
O caminho errado: global
Como dito anteriormente, o escopo global é algo especial e as funções podem importar explicitamente variáveis dele:
$foo = 'bar';
function baz() {
global $foo;
echo $foo;
$foo = 'baz';
}
Esta função usa e modifica a variável global $foo
. Não faça isso! (A menos que você realmente saiba realmente o que está fazendo e, mesmo assim: não saiba!)
Todo o chamador desta função vê é o seguinte:
baz(); // outputs "bar"
unset($foo);
baz(); // no output, WTF?!
baz(); // outputs "baz", WTF?!?!!
Não há indicação de que essa função tenha efeitos colaterais , mas tem. Isso facilmente se torna uma bagunça emaranhada, pois algumas funções continuam modificando e exigindo algum estado global. Você quer que as funções sejam sem estado , agindo apenas em suas entradas e retornando saídas definidas, por mais que você as chame.
Você deve evitar usar o escopo global da maneira mais possível; certamente você não deve estar "puxando" variáveis do escopo global para um escopo local.