Променливи
PHP Manual

Област на действие на променливи

Област на действие или обхват (scope) на променлива е контекстът, в който тя е дефинирана. На повечето места променливите в PHP имат само една област на действие. Тази единствена област на действие се разпростира също и във включените и в изискваните файлове. Например:

<?php
$a 
1;
include 
'b.inc';
?>

Тук променливата $a ще бъде налична във включения скрипт b.inc. В рамките на потребителски-дефинирани функции, обаче, се въвежда локална област на действие. Всяка променлива, използвана вътре във функция, по подразбиране е ограничена в локалната област на действие на функцията. Например:

<?php
$a 
1/* глобална област на действие */ 

function test()

    echo 
$a/* референция към променлива от локалната област на действие */ 


test();
?>

Този скрипт няма да изведе нищо, защото изразът echo се отнася за локална версия на променливата $a, а тя няма присвоена стойност в тази област на действие. Вероятно забелязвате, че това е малко по-различно от езика C с това, че в C променливите са налични автоматично във функциите, освен ако не са отменени от локална дефиниция. Това може да създаде проблеми, тъй като човек може по невнимание да промени глобална променлива. В PHP глобалните променливи трябва да бъдат декларирани като глобални вътре в дадена функция, ако ще бъдат използвани в тази функция.

Ключовата дума global

Първо, примерна употреба на global:

Example #1 Употреба на global

<?php
$a 
1;
$b 2;

function 
Sum()
{
    global 
$a$b;

    
$b $a $b;


Sum();
echo 
$b;
?>

Горният скрипт ще изведе "3". Декларирайки $a и $b като глобални за функцията, всички референции към променливите ще сочат към глобалната версия. Няма ограничение в броя на глобалните променливи, които могат да бъдат манипулирани от функция.

Вторият начин за достъп до променливи от глобалния обхват е да се използва специалния масив $GLOBALS в PHP. Предният пример може да бъде пренаписан така:

Example #2 Използване на $GLOBALS вместо global

<?php
$a 
1;
$b 2;

function 
Sum()
{
    
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];


Sum();
echo 
$b;
?>

$GLOBALS е асоциативен масив, в който името на глобалната променлива е ключът, а съдържанието на тази променлива е стойността на елемента от масива. Забележете, че $GLOBALS е наличен във всяка област на действие, a това е така, тъй като $GLOBALS е свръхглобален. Ето пример, демонстриращ възможностите на свръхглобалните:

Example #3 Пример, показващ свръхглобални и обхват

<?php
function test_global()
{
    
// Повечето предварително-дефинирани променливи не са "super" и изискват
    // 'global', за да бъдат налични в локалния обхват на функция.
    
global $HTTP_POST_VARS;
    
    echo 
$HTTP_POST_VARS['name'];
    
    
// Свръхглобалните са налични във всеки обхват и
    // не изискват 'global'. Свръхглобалните са налични
    // от PHP 4.1.0, и сега HTTP_POST_VARS се
    // смята за непрепоръчителен.
    
echo $_POST['name'];
}
?>

Използване на статични променливи

Друга важна особеност на обхвата на променливите е статичната променлива. Статичната променлива съществува единствено в локалната област на действие на функцията, но не губи стойността си, когато изпълнението на програмата напусне тази област. Разгледайте следния пример:

Example #4 Пример, показващ нуждата от статични променливи

<?php
function test()
{
    
$a 0;
    echo 
$a;
    
$a++;
}
?>

Тази функция е напълно безполезна, тъй като всеки път, когато бива извикана, тя установява $a в 0 и отпечатва "0". Изразът $a++ , който инкрементира променливата, е безсмислен, понеже в момента, в който функцията излезе, променливата $a изчезва. За да направим полезна брояща функция, която да не губи представа за текущата сума, променливата $a се дефинира като статична:

Example #5 Примерна употреба на статични променливи

<?php
function test()
{
    static 
$a 0;
    echo 
$a;
    
$a++;
}
?>

Тук $a се инициализира само при първото извикване на функцията и при всяко следващо извикване на test(), тя ще отпечатва стойността на $a и ще я инкрементира.

Статичните променливи предоставят също и начин за работа с рекурсивни функции. Рекурсивна функция е такава, която извиква сама себе си. Трябва да се внимава при писане на рекурсивна функция, защото е възможно тя да бъде принудена да се самоизвиква до безкрайност. Трябва да се уверите, че имате подходящ начин за спиране на рекурсията. Следната проста функция брои рекурсивно до 10, използвайки статичната променлива $count, за да разбере кога да спре:

Example #6 Статични променливи с рекурсивни функции

<?php
function test()
{
    static 
$count 0;

    
$count++;
    echo 
$count;
    if (
$count 10) {
        
test();
    }
    
$count--;
}
?>

Забележка: Статичните променливи могат да бъдат декларирани, както в примерите по-горе. Опитът да се присвоят стойности на тези променливи, които са резултат от изрази, ще причини грешка в разбора (parse error).

Example #7 Деклариране на статични променливи

<?php
function foo(){
    static 
$int 0;          // правилно 
    
static $int 1+2;        // грешно  (тъй като е израз)
    
static $int sqrt(121);  // грешно  (тъй като също е израз)

    
$int++;
    echo 
$int;
}
?>


Референции с глобални и статични променливи

Zend Engine 1, управляваща PHP 4, реализира static и global модификаторите за променливи от гледна точка на референции. Например, истинска глобална променлива, внесена в обхвата на функция посредством израза global, в действителност създава референция към глобалната променлива. Това може да доведе до неочаквано поведение, за което става дума и в следващия пример:

<?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);
?>

Изпълнението на този пример ще изведе следното:


NULL
object(stdClass)(0) {
}

Подобно поведение е в сила и за израза static. Референциите не се пазят статично:

<?php
function &get_instance_ref() {
    static 
$obj;

    echo 
'Static object: ';
    
var_dump($obj);
    if (!isset(
$obj)) {
        
// Присвояване на референция на статичната променлива
        
$obj = &new stdclass;
    }
    
$obj->property++;
    return 
$obj;
}

function &
get_instance_noref() {
    static 
$obj;

    echo 
'Static object: ';
    
var_dump($obj);
    if (!isset(
$obj)) {
        
// Присвояване на обект на статичната променлива
        
$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();
?>

Изпълнението на този пример ще изведе следното:


Static object: NULL
Static object: NULL

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

Този пример показва, че когато присвоявате референция на статична променлива, при извикването на функцията &get_instance_ref() за втори път, тя не е запомнена.


Променливи
PHP Manual