Какие области видимости переменных существуют в PHP?

«Какие области видимости переменных существуют в PHP?» — вопрос из категории PHP Core, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В PHP существует несколько областей видимости переменных, которые определяют, где переменная доступна для использования. Вот основные из них с практическими примерами:

1. Глобальная область видимости Переменные, объявленные вне функций, методов или классов.

<?php
// Глобальная область видимости
$globalVar = "Я глобальная переменная";
$counter = 0;

function testGlobal() {
    // Внутри функции $globalVar НЕ доступна
    // echo $globalVar; // Вызовет Notice: Undefined variable

    // Способ 1: Использование global
    global $globalVar, $counter;
    echo $globalVar; // Теперь доступна
    $counter++; // Можем изменять

    // Способ 2: Использование $GLOBALS суперглобального массива
    echo $GLOBALS['globalVar'];
    $GLOBALS['counter']++;
}

testGlobal();
echo $counter; // Выведет: 2 (было увеличено дважды)

2. Локальная область видимости (внутри функций) Переменные, объявленные внутри функции, доступны только в этой функции.

function calculateTotal($price, $quantity) {
    // $price и $quantity - параметры функции, локальные для этой функции
    $taxRate = 0.20; // Локальная переменная
    $subtotal = $price * $quantity;
    $tax = $subtotal * $taxRate;

    return $subtotal + $tax;
}

$total = calculateTotal(100, 2);
// echo $taxRate; // Ошибка! $taxRate не существует вне функции
// echo $subtotal; // Ошибка! $subtotal не существует вне функции

3. Статические переменные Сохраняют свое значение между вызовами функции.

function getNextId() {
    static $id = 0; // Инициализируется только при первом вызове
    $id++;
    return $id;
}

echo getNextId(); // 1
echo getNextId(); // 2
echo getNextId(); // 3

// Полезно для кеширования тяжелых вычислений
function heavyCalculation($input) {
    static $cache = [];

    if (isset($cache[$input])) {
        return $cache[$input];
    }

    // Тяжелые вычисления...
    $result = expensiveComputation($input);
    $cache[$input] = $result;

    return $result;
}

4. Область видимости в классах (свойства)

class User {
    // Public - доступно отовсюду
    public $publicProperty = "Доступно везде";

    // Protected - доступно внутри класса и наследников
    protected $protectedProperty = "Доступно в классе и наследниках";

    // Private - доступно только внутри этого класса
    private $privateProperty = "Доступно только в этом классе";

    public function getPrivateProperty() {
        return $this->privateProperty; // Доступно внутри класса
    }
}

class Admin extends User {
    public function getProtectedProperty() {
        return $this->protectedProperty; // Доступно в наследнике
    }

    public function tryGetPrivate() {
        // return $this->privateProperty; // Ошибка! Не доступно в наследнике
    }
}

$user = new User();
echo $user->publicProperty; // OK
// echo $user->protectedProperty; // Ошибка!
// echo $user->privateProperty; // Ошибка!
echo $user->getPrivateProperty(); // OK - через публичный метод

5. Суперглобальные массивы Особый тип переменных, доступных везде в скрипте:

// $_GET, $_POST, $_REQUEST - данные от пользователя
// $_SESSION - данные сессии
// $_COOKIE - куки
// $_SERVER - информация о сервере
// $_ENV - переменные окружения
// $_FILES - загруженные файлы

function processForm() {
    // Суперглобальные доступны везде без объявления global
    $name = $_POST['name'] ?? 'Гость';
    $ip = $_SERVER['REMOTE_ADDR'];

    // Важно: всегда валидировать и санитизировать данные из суперглобальных!
    $cleanName = htmlspecialchars($name, ENT_QUOTES, 'UTF-8');

    return "Привет, $cleanName с IP $ip";
}

6. Замыкания (closures) и use

$multiplier = 10;

// use передает переменную из внешней области видимости
$closure = function($number) use ($multiplier) {
    return $number * $multiplier;
};

echo $closure(5); // 50

// По значению (по умолчанию)
$counter = 0;
$increment = function() use ($counter) {
    // $counter копируется, изменения не влияют на оригинал
    return ++$counter;
};
echo $increment(); // 1
echo $increment(); // 2
echo $counter; // 0 - оригинал не изменился

// По ссылке
$counter = 0;
$incrementRef = function() use (&$counter) {
    return ++$counter;
};
echo $incrementRef(); // 1
echo $incrementRef(); // 2
echo $counter; // 2 - оригинал изменился

Практические рекомендации:

  1. Избегайте глобальных переменных - они усложняют тестирование и понимание кода
  2. Используйте параметры функций вместо global
  3. Применяйте статические переменные для кеширования и счетчиков
  4. Соблюдайте инкапсуляцию в классах (private/protected где возможно)
  5. Всегда валидируйте суперглобальные переменные

Понимание областей видимости критически важно для написания чистого, поддерживаемого и безопасного PHP-кода.