O escopo de uma variável é o contexto onde foi definida. A maioria das variáveis do PHP tem somente escopo local. Este escopo local inclui os arquivos incluídos e requeridos. Por exemplo:
<?php
$a = 1;
include 'b.inc';
?>
Aqui a variável $a estará disponível no script incluído b.inc. Entretanto, nas funções definidas pelo usuário, um escopo local é introduzido. Qualquer variável utilizada dentro de uma função é, por padrão, limitada ao 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) */
}
Teste();
?>
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 não possui nenhum valor atribuído neste escopo. Pode-se perceber que esta é uma pequena diferença em relação a linguagem C, em que variáveis globais estão automaticamente disponíveis para funções sem sobrescrever uma definição local. Isto pode causar problemas quando inadvertidamente modificar-se uma variável global. No PHP, as variáveis globais precisam ser declaradas como globais dentro de uma função, se for utilizada em uma.
Primeiro, um exemplo de global:
Exemplo #1 Usando global
<?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, fará com que todas as referências a essas variáveis referenciem a versão global. Não há 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 reescrito como:
Exemplo #2 Usando $GLOBALS no lugar de global
<?php
$a = 1;
$b = 2;
function Soma()
{
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
}
Soma();
echo $b;
?>
O array $GLOBALS é um array associativo, sendo 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:
Exemplo #3 Exemplo demonstrando superglobals e escopos
<?php
function test_global()
{
// A maioria das variaveis pré-definidas nao sao 'super' e requerem
// 'global' para serem disponiveis para funcoes em qualquer escopo.
global $HTTP_POST_VARS;
echo $HTTP_POST_VARS['name'];
// Superglobais são disponiveis em qualquer escopo e
// nao precisam de 'global'. Superglobais existem
// desde o PHP 4.1.0, e HTTP_POST_VARS é agora
// tida como obsoleta.
echo $_POST['name'];
}
?>
Nota:
Utilizar a instrução global fora de uma função não é um erro. Deve ser utilizado se um arquivo for incluído dentro de uma função.
Outro recurso importante do escopo de variáveis é a variável static. Uma variável estática existe somente no escopo local da função, mas não perde seu valor quando o nível de execução do programa deixa o escopo. Considere o seguinte exemplo:
Exemplo #4 Exemplo demonstrando a necessidade de variáveis estáticas
<?php
function Teste()
{
$a = 0;
echo $a;
$a++;
}
?>
Essa função é inútil, já que cada vez que é chamada, define $a com o valor 0, e imprime 0. A instrução $a++ , que aumenta o valor da variável, não tem sentido já que assim que a função termina a variável $a desaparece. Para fazer um função contadora, que não perderá a conta atual, a variável $a será declarada como estática:
Exemplo #5 Exemplo de uso de variáveis estáticas
<?php
function Teste()
{
static $a = 0;
echo $a;
$a++;
}
?>
Agora, a variável $a é inicializada apenas na primeira chamada da função e cada vez que a função test() for chamada, imprimirá o valor de $a e depois o incrementará.
Variáveis estáticas fornecem uma solução para lidar com funções recursivas. Uma função recursiva é aquela chama a si mesma. Cuidados devem ser tomados quando escrever funções recursivas porque é possível que ela continue na recursão indefinidamente. Deve-se assegurar que há uma maneira adequada de terminar a recursão. A seguinte função recursiva conta até 10, utilizando a variável estática $count para saber quando parar:
Exemplo #6 Variáveis estáticas em funções recursivas
<?php
function Teste()
{
static $count = 0;
$count++;
echo $count;
if ($count < 10) {
Teste();
}
$count--;
}
?>
Nota:
Variáveis estáticas podem ser declaradas como visto nos exemplos acima. Tentar atribuir valores a essas variáveis, que são resultados de expressões, causarão um erro de interpretação.
Exemplo #7 Declarando variáveis estáticas
<?php
function foo(){
static $int = 0; // correro
static $int = 1+2; // errado (é uma expressão)
static $int = sqrt(121); // wrong (é uma expressão também)
$int++;
echo $int;
}
?>
Nota:
Declarações estáticas são resolvida em tempo de compilação.
A Zend Engine 1, base do PHP 4, implementa os modificadores static e global para variáveis, em termo de referências. Por exemplo, uma variável global verdadeira, importada dentro do escopo de uma função com a instrução global, na verdade, cria uma referência para a variável global. Isto pode levar a comportamentos imprevisíveis nos seguintes casos:
<?php
function test_global_ref() {
global $obj;
$obj = &new stdclass;
}
function test_global_noref() {
global $obj;
$obj = new stdclass;
}
test_global_ref();
var_dump($obj);
test_global_noref();
var_dump($obj);
?>
O exemplo acima irá imprimir:
Um comportamento similar se aplica a declaração 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();
?>
O exemplo acima irá imprimir:
Este exemplo demonstra que, atribuir uma referência a uma variável estática, fará com que ela não se lembre quando chamou a função &get_instance_ref() uma segunda vez.