Что такое поднятие переменных (hoisting) в PHP?

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

Ответ

В отличие от JavaScript, в PHP нет классического hoisting'а (поднятия) объявлений переменных. Переменная в PHP не существует до момента её явного объявления в коде.

Ключевое правило: Обращение к переменной до её инициализации вызовет предупреждение или ошибку.

// Пример 1: Ошибка доступа к необъявленной переменной
echo $undefinedVar; // Notice: Undefined variable: undefinedVar
$undefinedVar = 10;

// Пример 2: Переменная существует только после объявления внутри области видимости
function test() {
    // echo $localVar; // Если раскомментировать, будет Notice
    $localVar = "I exist now";
    echo $localVar; // Корректно: "I exist now"
}

Особые случаи, которые иногда путают с поднятием:

  1. Глобальные переменные и ключевое слово global:

    $globalVar = "outside";
    function testGlobal() {
        // echo $globalVar; // Notice! $globalVar здесь не определена
        global $globalVar; // Ссылка на глобальную переменную создается здесь
        echo $globalVar; // Корректно: "outside"
    }
    testGlobal();

    Ключевое слово global не "поднимает" переменную, а создаёт ссылку на уже существующую глобальную переменную в момент выполнения строки с global.

  2. Статические переменные внутри функций:

    function counter() {
        static $count = 0; // Инициализация происходит ТОЛЬКО при первом вызове функции
        $count++;
        echo $count;
    }
    counter(); // 1
    counter(); // 2

    Переменная $count сохраняет своё значение между вызовами функции, но это не hoisting. Область видимости статической переменной ограничена функцией.

  3. Поднятие функций и классов:

    // В PHP функции и классы, объявленные обычным образом, "поднимаются".
    foo(); // Работает, выведет "Hello!"
    function foo() {
        echo "Hello!";
    }
    
    // Однако анонимные функции (замыкания), присвоенные переменным, не поднимаются.
    // bar(); // Fatal error, если раскомментировать
    $bar = function() { echo "Anonymous"; };
    $bar(); // Корректно

Вывод:

  • Для переменных: Hoisting отсутствует. Всегда объявляйте и инициализируйте переменные перед использованием.
  • Для функций/классов: Традиционные объявления (через function и class) поднимаются и могут быть вызваны до их места объявления в файле.
  • Область видимости в PHP в основном определяется функциями и классами, а не блоками {}, как в JavaScript (за исключением анонимных функций/замыканий).