W3docs

Статические свойства в PHP ООП

Статическое свойство принадлежит классу, а не конкретному объекту. Оно существует в единственном экземпляре и разделяется всеми объектами класса.

Статическое свойство принадлежит самому классу, а не какому-либо отдельному объекту, созданному на его основе. Тогда как обычное (экземплярное) свойство получает собственную копию в каждом объекте, статическое свойство существует ровно в одном экземпляре и разделяется всеми экземплярами — измените его в одном месте, и все объекты увидят новое значение. На этой странице объясняется, как объявлять статические свойства, как их читать и записывать, чем отличаются self, static и parent, как они ведут себя при наследовании, и на какие подводные камни стоит обратить внимание.

Если вы только начинаете знакомство с классами PHP, сначала прочитайте Классы и объекты PHP.

Что такое статическое свойство?

Статическое свойство объявляется с ключевым словом static в сочетании с модификатором видимости (public, protected или private):

<?php

class User {
    public static int $count = 0;

    public function __construct() {
        self::$count++;
    }
}

new User();
new User();
new User();

echo User::$count; // 3

Три вещи отличают статическое свойство от обычного:

  • Доступ через класс, а не через объект. Вы пишете User::$count с оператором разрешения области видимости ::, а не $user->count. Попытка прочитать статическое свойство через оператор стрелки ($user->count) не работает и генерирует предупреждение.
  • Общее, а не скопированное. Каждый new User() увеличивает одно и то же $count. В памяти для всего класса существует только одна копия.
  • Внутри класса используется self::$count. Внутри метода к свойству обращаются через self::, static:: или parent:: — но не через $this.

Чтение и запись статического свойства

Внутри класса используйте self::$property. СнаружиClassName::$property. Поскольку существует только одна копия, запись из любого контекста видна повсюду:

<?php

class Counter {
    public static int $value = 0;

    public static function increment(): void {
        self::$value++;
    }
}

Counter::increment();
Counter::increment();
Counter::$value += 10; // also writable directly from outside

echo Counter::$value; // 12

Статическое свойство может иметь значение по умолчанию, но оно должно быть константным выражением (литералом, константой или простым арифметическим выражением с const) — результат вызова функции или объект new недопустимы.

self:: и static:: (позднее статическое связывание)

Внутри метода к статическому свойству можно обратиться через self:: или static::. Они отличаются при наследовании:

  • self:: разрешается во время компиляции и всегда указывает на класс, в котором написан код.
  • static:: использует позднее статическое связывание — оно указывает на класс, на котором вызван метод во время выполнения.
<?php

class Base {
    public static string $label = "Base";

    public static function whoAmISelf(): string {
        return self::$label;   // bound to Base
    }

    public static function whoAmIStatic(): string {
        return static::$label; // bound to the calling class
    }
}

class Child extends Base {
    public static string $label = "Child";
}

echo Child::whoAmISelf();  // Base
echo "\n";
echo Child::whoAmIStatic(); // Child

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

Когда использовать статические свойства?

Статические свойства хорошо подходят, когда состояние должно быть общим для всех экземпляров класса:

  • Подсчёт экземпляров — пример User::$count выше отслеживает количество существующих объектов.
  • Кэширование / реестры — хранение таблицы поиска или единственного общего ресурса (например, дескриптора соединения с базой данных), чтобы он создавался один раз и повторно использовался.
  • Конфигурация или флаги — значение по умолчанию, применяемое ко всему классу, например глобальный User::$defaultRole.
  • Паттерн Singleton — приватное статическое свойство хранит единственный экземпляр, возвращаемый методом getInstance().

Если значение не должно изменяться после объявления, предпочтите константу класса (const) — она лучше выражает намерение и не может быть переназначена.

Распространённые подводные камни

  • Статические свойства — не константы. Они изменяемы; любой код с доступом может переназначить их. Используйте const для значений, которые не должны меняться.
  • Общее состояние — обоюдоострый меч. Поскольку все экземпляры разделяют значение, изменение в одном объекте отражается везде — удобно для счётчиков, опасно, если вы ожидали данные на уровне объекта.
  • Нет $this в статическом контексте. У статических методов нет $this, поэтому к статическому свойству нужно обращаться через self::, static:: или parent::.
  • При наследовании подкласс разделяет хранилище родителя, если не переобъявляет свойство. Подкласс, который не переобъявляет статическое свойство, разделяет единственную копию родителя; переобъявление (как делает Child выше) даёт подклассу собственную копию.

Заключение

Статические свойства позволяют классу хранить состояние, общее для всех его экземпляров, — доступ к нему осуществляется через имя класса с оператором :: и через self::/static:: внутри класса. Они идеально подходят для счётчиков, кэшей, реестров и паттерна Singleton. Используйте const класса, когда значение должно оставаться неизменным, и помните, что static:: обеспечивает позднее статическое связывание, позволяя подклассам переопределять значение. Далее изучите Статические методы PHP и Наследование в PHP, чтобы увидеть, как эти элементы сочетаются друг с другом.

Практика

Практика
Что верно относительно статических свойств PHP?
Что верно относительно статических свойств PHP?
Was this page helpful?