Какие области видимости переменных существуют в 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-кода.

Ответ 18+ 🔞

А, PHP и его области видимости, ебать мои старые костыли! Ну, смотри, тут история как с квартирой: есть где можно ходить в трусах, а где надо хотя бы штаны натянуть, иначе соседи охуеют.

1. Глобальная область — это как улица Объявил переменную на улице — ну, типа, всем видно. Но зайди в подъезд (функцию) — нихуя не видно, хоть тресни.

<?php
// Вот стоишь на улице, орешь на всю Ивановскую
$globalVar = "Я глобальная переменная";
$counter = 0;

function testGlobal() {
    // Зашел в подъезд — тишина, нихуя не слышно
    // echo $globalVar; // Выдаст тебе: "Э, дружок, а чё это за переменная? Не знаю я её"

    // Вариант первый: крикни "Эй, глобальные, я про вас помню!"
    global $globalVar, $counter;
    echo $globalVar; // Теперь услышали
    $counter++; // И даже покрутили

    // Вариант второй: посмотри в волшебную книгу всех жильцов
    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; // Ошибка! На улице про твою бутылку никто не знает
// echo $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. Область видимости в классах — это как доступ в комнаты Есть общая комната (public), есть кабинет (protected), а есть сейф (private).

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; // Ну коридор же, заходи
// echo $user->protectedProperty; // Ошибка! Тебя в кабинет не звали
// echo $user->privateProperty; // Ошибка! Сейф вообще не твоя тема
echo $user->getPrivateProperty(); // А вот так, через доверенного, можно

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. Замыкания и 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. В классах прячь всё, что можно. Public — только то, что реально надо наружу. Всё остальное — под замок, чтоб не сломали.
  5. Суперглобальные — обрабатывай как бомбу. Проверяй, чисть, экранируй, а то будет тебе хиросима с нигерсраками.

Короче, если разобраться с областями видимости — код станет чище, багов меньше, а жизнь веселее. А если нет — сам от себя охуеешь через месяц, когда будешь искать, где же эта переменная поменялась.