В PHP каждый объект — это отдельный экземпляр класса со своим набором данных. Но иногда нужно иметь данные или поведение, которые принадлежат не конкретному объекту, а самому классу целиком. Именно для этого существуют статические свойства и методы. Они живут на уровне класса, разделяются всеми его экземплярами и доступны даже без создания объекта.
Экземпляр против класса: в чём разница
Чтобы понять статику, важно чётко разделить два понятия. Обычные свойства и методы принадлежат экземпляру — каждый объект хранит свои значения отдельно. Статические свойства и методы принадлежат классу — они существуют в единственном экземпляре в памяти и общие для всех объектов этого класса.
Обычный (экземпляр)
Уровень объекта
- Каждый объект хранит свои данные
- Доступ через $this->
- Требует создания объекта
- Состояние изолировано
Статический (класс)
Уровень класса
- Одно значение на весь класс
- Доступ через self::или ClassName::
- Доступен без создания объекта
- Состояние общее для всех
Как статическое свойство живёт в памяти
Объект #1
$name = "Алексей"
$email = "a@b.ru"
Объект #2
$name = "Мария"
$email = "m@b.ru"
Объект #3
$name = "Иван"
$email = "i@b.ru"
Класс User — статическое свойство (общее)
static $count = 3 ← разделяется всеми объектами
Статические свойства
Статическое свойство объявляется с ключевым словом static. Обращаться к нему внутри класса принято через self::, а снаружи — через имя класса и оператор :: (который называется оператором разрешения области видимости).
class User
{
// Статическое свойство: считает всех созданных пользователей
private static int $count = 0;
public function __construct(
public readonly string $name
) {
// При создании каждого объекта увеличиваем общий счётчик
self::$count++;
}
public static function getCount(): int
{
return self::$count;
}
}
$u1 = new User('Алексей');
$u2 = new User('Мария');
$u3 = new User('Иван');
echo User::getCount(); // 3 — без создания нового объекта
Статические методы
Статический метод объявляется с ключевым словом static перед function. Внутри него нет доступа к $this — потому что статический метод вызывается без объекта и не знает ни о каком конкретном экземпляре.
Вызвать статический метод можно двумя способами: через имя класса (ClassName::method()) или изнутри самого класса через self::method().
class Temperature
{
public function __construct(
public readonly float $celsius
) {}
// Статический метод-фабрика: создаёт объект из градусов Фаренгейта
public static function fromFahrenheit(float $f): static
{
return new static(($f - 32) / 1.8);
}
// Статический вспомогательный метод: просто конвертация
public static function celsiusToKelvin(float $c): float
{
return $c + 273.15;
}
public function toKelvin(): float
{
// Внутри обычного метода можно вызвать статический через self::
return self::celsiusToKelvin($this->celsius);
}
}
// Вызов без создания объекта
echo Temperature::celsiusToKelvin(100); // 373.15
// Статический фабричный метод создаёт объект
$t = Temperature::fromFahrenheit(212);
echo $t->celsius; // 100
echo $t->toKelvin(); // 373.15
self:: против static:: — позднее статическое связывание
В PHP есть тонкость, которую важно понимать при наследовании: разница между self:: и static::. Ключевое слово self:: всегда ссылается на класс, в котором метод написан. А static:: ссылается на класс, через который метод был вызван. Это называется поздним статическим связыванием (Late Static Binding).
class Base
{
public static function createSelf(): static
{
return new self(); // всегда создаёт Base
}
public static function createStatic(): static
{
return new static(); // создаёт тот класс, через который вызван
}
}
class Child extends Base {}
$a = Child::createSelf(); // объект Base — self не «видит» Child
$b = Child::createStatic(); // объект Child — static учитывает контекст
echo get_class($a); // Base
echo get_class($b); // Child
Статические свойства и методы — это не просто «методы без объекта». Это способ выразить в коде тот факт, что некоторые данные или поведение относятся к самому классу, а не к его отдельным экземплярам. Они разделяются всеми объектами, живут на уровне класса и доступны без создания объекта через оператор ::.
Главное правило применения статики: используйте её там, где отсутствие $this — это намеренное решение, а не случайное упущение. Утилитарные методы, фабрики, счётчики, паттерн Singleton — всё это разумные кандидаты. Избегайте превращать обычную логику в статическую только ради удобства вызова: это усложняет тестирование и нарушает принципы ООП.
0 Комментарий(я)
Зарегистрируйтесь чтобы оставить комментарий