Escopo de variáveis

O escopo de uma variável é o contexto onde ela foi definida . A maior parte das variáveis do PHP tem somente escopo local . Este escopo local inclui os arquivos incluídos . Por exemplo :




Aqui a variável $a estará disponível no script incluído b.inc . Entretanto , com as funções definidas pelo usuário , um escopo local é introduzido . Quaisquer variáveis utilizadas dento da função é por default limitada dentro do escopo local da função . Por exemplo :

 
?php

 
$a

 
=

 
1

 
;

 
/

 
*

 
escopo

 
global

 
*

 
/

 
function

 
Teste(

 
)

 
{

 
echo

 
$a

 
;

 
/

 
*

 
referencia

 
uma

 
variável

 
do

 
escopo

 
local

 
(não

 
definida

 
)

 
*

 
/

 
}

 
Test()

 
;

 
?



Este script não produz nenhuma saída porque a instrução echo( ) refere-se a uma versão local da variável $a , e ela não tem nenhum valor assimilado nesse escopo . Essa é uma pequena diferença da linguagem C quando variáveis globais são automaticamente disponíveis para funções sem sobreescrever uma eventual definição local . Isto causa problemas quando as pessoas mudam inadivertidamente uma variável global . No PHP , as variáveis globais precisam ser declaradas globais dentro de uma função se ela vai ser utilizada naquela função . Um exemplo :

 
?php

 
$a

 
=

 
1

 
;

 
$b

 
=

 
2

 
;

 
function

 
Soma(

 
)

 
{

 
global

 
$a

 
,

 
$b

 
;

 
$b

 
=

 
$a

 
+

 
$b

 
;

 
}

 
Soma()

 
;

 
echo

 
$b

 
;

 
?



O script acima imprimirá " 3 " . Declarando $a e $b globais na função , todas as referências a essas variáveis referem-se a versão global . Não um limite para o número de variáveis globais que podem ser manipuladas por uma função .

Uma segunda maneira de acessar variáveis do escopo global é utilizando o array especial $GLOBALS definido pelo PHP . O exemplo anterior poderia ser rescrito como :

 
?php

 
$a

 
=

 
1

 
;

 
$b

 
=

 
2

 
;

 
function

 
Soma(

 
)

 
{

 
$GLOBALS["b"

 
]

 
=

 
$GLOBALS["a"

 
]

 
+

 
$GLOBALS["b"]

 
;

 
}

 
Soma()

 
;

 
echo

 
$b

 
;

 
?



O array $GLOBALS é um array associativo onde o nome da variável global é a chave do array e o seu conteúdo da variável como o valor do elemento do array . Veja que $GLOBALS existe em qualquer escopo , isto porque $GLOBALS é uma superglobal . Segue um exemplo demonstrando o poder das superglobais :

 
?php

 
function

 
test_global(

 
)

 
{

 
/

 
/

 
A

 
maioria

 
das

 
variaveis

 
predefinidas

 
nao

 
sao

 
'super

 
'

 
e

 
requerem

 
/

 
/

 
'global

 
'

 
para

 
serem

 
disponiveis

 
para

 
funcoes

 
em

 
qualquer

 
escopo

 
.

 
global

 
$HTTP_POST_VARS

 
;

 
print

 
$HTTP_POST_VARS['name']

 
;

 
/

 
/

 
Superglobais

 
são

 
disponiveis

 
em

 
qualquer

 
escopo

 
e

 
/

 
/

 
nao

 
precisam

 
de

 
'global

 
'

 
.




 
Superglobais

 
existem

 
/

 
/

 
desde

 
o

 
PHP

 
4.1.0

 
print

 
$_POST[

 
'name']

 
;

 
}

 
?





Outro recurso importante do escopo de variáveis é a variável estática . Uma variável estática existe somente no escopo local da função , mas ela não perde seu valor quando o nível de execução do programa deixa o escopo . Considere o seguinte exemplo :

 
?php

 
function

 
Teste

 
(

 
)

 
{

 
$a

 
=

 
0

 
;

 
echo

 
$a

 
;

 
$a++

 
;

 
}

 
?



Essa função é inútil partindo de que cada vez que ela é chamada , ela coloca em $a o valor 0 e imprime " 0 " . A instrução $a + + , que aumenta o valor da variável não tem sentido desde que a função sai e a variável $a desaparece . Para faze-la mais útil como contadora sem deixar de perder o sua conta atual , a variável $a é declarada como estática :

 
?php

 
function

 
Teste(

 
)

 
{

 
static

 
$a

 
=

 
0

 
;

 
echo

 
$a

 
;

 
$a++

 
;

 
}

 
?



Agora , cada vez que a função Teste( ) for chamada ele imprimirá o valor de $a e o incrementará .

Variáveis estáticas fornecem uma solução ideal para funções recursivas . Uma função recursiva é aquela se chama a si mesma . Cuidados especiais precisam ser tomados quando escrevendo funções recursivas porque é possível que ela continue na recursão indefinidamente . Você tem de ter certeza que uma maneira segura de terminar a recursão . A seguinte função recursiva conta até 10 , utilizando a variável estática $count para saber quando parar :

 
?php

 
function

 
Teste(

 
)

 
{

 
static

 
$count

 
=

 
0

 
;

 
$count++

 
;

 
echo

 
$count

 
;

 
if

 
($count

 
10

 
)

 
{

 
Test

 
()

 
;

 
    }

 
$count--

 
;

 
}

 
?



O Zend Engine 1 , base do PHP4 , implementa os modificadores static e global para variáveis em termos de referência . Por exemplo , uma variável global importada dentro do escopo de uma função com a instrução global atualmente cria uma referência para a variável global . Isto pode causar comportamentos impresíveis para os seguintes casos :




Executando esse exemplo você terá as seguites saídas :




Uma situação similar se aplica ao modificador static . Referências não são armazenadas estaticamente :

 
?php

 
function

 
get_instance_ref(

 
)

 
{

 
static

 
$obj

 
;

 
echo

 
"Objeto

 
estatico

 
:

 
"

 
;

 
var_dump($obj)

 
;

 
if

 
(!isset($obj)

 
)

 
{

 
/

 
/

 
Assimila

 
uma

 
referencia

 
a

 
variavel

 
estatica

 
$obj

 
=

 
new

 
stdclass

 
;

 
    }

 
$obj

 
-

 
property++

 
;

 
return

 
$obj

 
;

 
}

 
function

 
get_instance_noref(

 
)

 
{

 
static

 
$obj

 
;

 
echo

 
"Objeto

 
estatico

 
:

 
"

 
;

 
var_dump($obj)

 
;

 
if

 
(!isset($obj)

 
)

 
{

 
/

 
/

 
Assimila

 
o

 
objeto

 
para

 
a

 
veriavel

 
estatica

 
$obj

 
=

 
new

 
stdclass

 
;

 
    }

 
$obj

 
-

 
property++

 
;

 
return

 
$obj

 
;

 
}

 
$obj1

 
=

 
get_instance_ref()

 
;

 
$still_obj1

 
=

 
get_instance_ref()

 
;

 
echo

 
"\n"

 
;

 
$obj2

 
=

 
get_instance_noref()

 
;

 
$still_obj2

 
=

 
get_instance_noref()

 
;

 
?



Executando esse exemplo você terá as seguites saídas :

 
Objeto

 
estatico

 
:




 
NULL

 
Objeto

 
estatico

 
:




 
NULL

 
Objeto

 
estatico

 
:




 
NULL

 
Objeto

 
estatico

 
:

 
object(

 
stdClass)(1

 
)

 
{

 
["property"]=

 
int(1

 
)

 
}



Este exemplo demonstra que quando assimilando uma referência para uma variável estática , ela não se lembra quando você chama a função get_instance_ref( ) uma segunda vez .