Статические свойства в 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, чтобы увидеть, как эти элементы сочетаются друг с другом.