Что такое ключевое слово `static` в 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 используется для создания функциональности, связанной с классом в целом, а не с его экземплярами, и для управления областью видимости переменных в функциях.

Ответ 18+ 🔞

Э, сабака сука, PHP и его static! Ну это ж классика, ёпта. Сидишь такой, пишешь код, а тут бац — нужно что-то общее для всех объектов сделать, а не плодить копии. Вот тут-то он и вылезает, этот самый static, как манна небесная.

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

Это когда какая-то фигня принадлежит самому классу, а не каждому отдельному объекту. Вызываешь её через ::, без всяких new. Как общая тумбочка в коридоре общежития — все туда свои носки кидают.

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::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 — это твой инструмент, когда нужно привязать логику или данные к самому классу, а не к его копиям-объектам, или когда нужно, чтобы функция помнила своё состояние между вызовами. Главное — не переборщить, а то получится спагетти-код, где всё статично и ничего не протестировать.