Область видимости (Scope)
В PHP функции имеют собственную область видимости. Переменные извне НЕ видны внутри функции автоматически.
<?php
declare(strict_types=1);
$globalVar = 'Hello';
function test(): void
{
// $globalVar is NOT accessible here!
// echo $globalVar; // Warning: Undefined variable
}
test();
Ключевое слово global
<?php
declare(strict_types=1);
$counter = 0;
function increment(): void
{
global $counter; // Import global variable
$counter++;
}
increment();
increment();
echo $counter; // 2
// Alternative: use $GLOBALS superglobal
function incrementAlt(): void
{
$GLOBALS['counter']++;
}
Запомни: Использование
globalсчитается плохой практикой. Вместо этого передавайте значения через параметры и возвращайте результат. Суперглобальные массивы ($_GET,$_POST,$_SERVERи т.д.) доступны везде безglobal.
Статические переменные
<?php
declare(strict_types=1);
function getNextId(): int
{
static $id = 0; // Initialized ONCE, persists between calls
return ++$id;
}
echo getNextId(); // 1
echo getNextId(); // 2
echo getNextId(); // 3
// Static variable initializer (PHP 8.1+: can use expressions)
function getConnection(): PDO
{
static $pdo = null;
if ($pdo === null) {
$pdo = new PDO('sqlite::memory:');
}
return $pdo;
}
// PHP 8.3+: static initializer with new
function getLogger(): Logger
{
static $logger = new Logger(); // PHP 8.3+
return $logger;
}
Ловушка экзамена: Статическая переменная инициализируется только ОДИН раз при первом вызове функции. Значение сохраняется между вызовами. С PHP 8.3 в инициализаторе можно использовать
newи другие выражения.
Передача по значению vs по ссылке
По значению (по умолчанию)
<?php
declare(strict_types=1);
function doubleValue(int $x): void
{
$x *= 2;
echo "Inside: $x\n";
}
$num = 5;
doubleValue($num); // Inside: 10
echo "Outside: $num"; // Outside: 5 — NOT changed!
По ссылке (&)
<?php
declare(strict_types=1);
function doubleReference(int &$x): void
{
$x *= 2;
}
$num = 5;
doubleReference($num);
echo $num; // 10 — CHANGED!
// Arrays are passed by value (copy-on-write)
function addItem(array $arr): void
{
$arr[] = 'new'; // Modifies local copy only
}
$items = ['a', 'b'];
addItem($items);
echo count($items); // 2 — unchanged
// Pass array by reference
function addItemRef(array &$arr): void
{
$arr[] = 'new';
}
addItemRef($items);
echo count($items); // 3 — modified!
Ловушка экзамена: Массивы передаются по значению (с copy-on-write оптимизацией). Копия создаётся только при модификации. Объекты всегда передаются по "идентификатору" — переменная содержит ссылку на объект, но сама передаётся по значению.
Объекты и ссылки
<?php
declare(strict_types=1);
class Counter
{
public int $value = 0;
}
// Objects: variable holds an object identifier (handle)
function incrementCounter(Counter $counter): void
{
$counter->value++; // Modifies THE SAME object
}
$c = new Counter();
incrementCounter($c);
echo $c->value; // 1 — changed!
// BUT: reassigning the variable doesn't affect original
function replaceCounter(Counter $counter): void
{
$counter = new Counter(); // Local variable now points to new object
$counter->value = 100;
}
replaceCounter($c);
echo $c->value; // Still 1! Not 100!
// With reference: reassignment DOES affect original
function replaceCounterRef(Counter &$counter): void
{
$counter = new Counter();
$counter->value = 100;
}
replaceCounterRef($c);
echo $c->value; // 100 — replaced!
Ссылки в деталях
<?php
declare(strict_types=1);
// Creating a reference
$a = 10;
$b = &$a; // $b is a reference to $a
$b = 20;
echo $a; // 20 — $a changed because $b is a reference
// Unsetting a reference
unset($b); // Only removes the reference, not the value
echo $a; // 20 — still exists
// References and arrays
$arr = [1, 2, 3];
$ref = &$arr[1]; // Reference to second element
$ref = 99;
echo $arr[1]; // 99
// Global creates a reference
$globalVar = 'original';
function modifyGlobal(): void
{
global $globalVar; // Creates local reference to global
$globalVar = 'modified';
}
modifyGlobal();
echo $globalVar; // 'modified'
// Functions returning references
function &getRef(array &$arr, int $key): mixed
{
return $arr[$key];
}
$data = [10, 20, 30];
$ref = &getRef($data, 1);
$ref = 99;
echo $data[1]; // 99
Ловушка экзамена:
unset()на ссылке удаляет только ссылочную связь, а НЕ значение.$a = 10; $b = &$a; unset($b);— переменная$aсо значением10остаётся нетронутой.unsetуничтожает только переменную$b.