Variáveis
PHP Manual

Escopo de variáveis

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.

A palavra-chave global

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.

Utilizando variáveis static

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.

Referencias em variáveis global e static

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:


NULL
object(stdClass)(0) {
}

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:


Objeto estatico: NULL
Objeto estatico: NULL

Objeto estatico: NULL
Objeto estatico: object(stdClass)(1) {
["property"]=>
int(1)
}

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.


Variáveis
PHP Manual