Что такое ключевое слово `static` в PHP?

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

Ответ

В PHP static — это ключевое слово с несколькими различными, но связанными значениями в зависимости от контекста использования.

1. Статические члены класса (свойства и методы)

Принадлежат самому классу, а не конкретному экземпляру (объекту). Вызываются через оператор разрешения области видимости ::.

class Logger {
    // Статическое свойство — общее для всех экземпляров и вызовов
    private static array $logEntries = [];

    // Статический метод — вызывается без создания объекта
    public static function log(string $message): void {
        self::$logEntries[] = date('Y-m-d H:i:s') . ': ' . $message;
    }

    public static function getLogs(): array {
        return self::$logEntries;
    }
}

// Использование без создания объекта Logger
Logger::log('Приложение запущено');
Logger::log('Пользователь вошел в систему');

print_r(Logger::getLogs());

Важно: Внутри статического метода нельзя использовать $this, так как он не привязан к объекту. Для доступа к другим статическим членам используется self:: или static::.

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

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

function getNextId(): int {
    static $counter = 0; // Инициализируется один раз
    $counter++;
    return $counter;
}

echo getNextId(); // 1
echo getNextId(); // 2
echo getNextId(); // 3
// Переменная $counter «помнит» свое значение

3. Позднее статическое связывание (Late Static Binding — LSB)

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

class ParentClass {
    public static function getName(): string {
        return static::class; // Позднее связывание: вернет имя реального вызывающего класса
        // return self::class; // Раннее связывание: всегда вернет 'ParentClass'
    }
}

class ChildClass extends ParentClass {}

echo ParentClass::getName(); // Вывод: 'ParentClass'
echo ChildClass::getName();  // Вывод: 'ChildClass' (благодаря static::)

LSB критически важен для реализации шаблона «Фабричный метод» и других паттернов в статическом контексте.

Итог: static используется для создания функциональности, связанной с классом в целом, а не с его экземплярами, и для управления областью видимости переменных в функциях.