🧱 Суть
Статические свойства и методы (static) принадлежат самому классу, а не отдельному объекту.
Обычные свойства и методы работают через объект:
$user = new User();
$user->name;
$user->login();Статические вызываются напрямую через класс:
User::$count;
User::create();📦 Проблема
1. Не всегда нужен объект
Иногда логика не относится к конкретному экземпляру.
Например:
- математические операции
- вспомогательные функции
- счётчики
- конфигурация
Создавать объект только ради одного действия бывает лишним:
$math = new Math();
$math->sum(2, 3);2. Общие данные между всеми объектами
Иногда нужно хранить значение, которое общее для всего класса.
Например:
Количество созданных пользователей
Версия приложения
Общие настройкиОбычное свойство хранится отдельно у каждого объекта.
✅ Решение
Использовать static, если значение или метод относятся к классу в целом, а не к конкретному объекту.
💻 Код
Статические свойства
Обычное свойство:
class User
{
public string $name;
}Каждый объект имеет свою копию:
$user1->name = "Alex";
$user2->name = "Bob";Статическое свойство:
class User
{
public static int $count = 0;
}Оно одно на весь класс.
Доступ:
echo User::$count;Изменение статического свойства
class User
{
public static int $count = 0;
public function __construct()
{
self::$count++;
}
}Теперь:
$user1 = new User();
$user2 = new User();
echo User::$count;Результат:
2Оба объекта изменяют одно значение.
Ключевое слово self
Внутри класса для обращения к статическим членам используется:
self::Пример:
class Config
{
public static string $appName = "My App";
public static function getName()
{
return self::$appName;
}
}Вызов:
Config::getName();Статические методы
Статический метод вызывается без создания объекта.
Пример:
class Math
{
public static function sum(int $a, int $b)
{
return $a + $b;
}
}Использование:
$result = Math::sum(5, 10);Отличие от обычного метода
Обычный метод:
class User
{
public function login()
{
echo "Login";
}
}
$user = new User();
$user->login();Статический метод:
class User
{
public static function validate()
{
echo "Valid";
}
}
User::validate();Ограничение static-методов
Статический метод не имеет $this.
Почему?
Потому что объекта нет.
Так нельзя:
class User
{
public string $name;
public static function showName()
{
echo $this->name;
}
}Ошибка:
Using $this when not in object contextself:: vs $this->
Обычный объект:
$this->name;Работает с конкретным объектом.
Статический контекст:
self::$name;Работает с классом.
Пример:
class Counter
{
public static int $value = 0;
public function increase()
{
self::$value++;
}
}Статические методы и наследование
Статические методы тоже могут наследоваться:
class User
{
public static function role()
{
echo "User";
}
}
class Admin extends User
{
}Вызов:
Admin::role();Работает.
static:: вместо self::
Есть важное отличие:
self::ссылается на класс, где метод написан.
static::использует вызывающий класс.
Пример:
class User
{
public static function name()
{
echo static::class;
}
}
class Admin extends User
{
}
Admin::name();Результат:
AdminЭто называется позднее статическое связывание.
Когда использовать static
Вспомогательные методы
class StringHelper
{
public static function slug(string $text)
{
return strtolower($text);
}
}Использование:
StringHelper::slug("Hello World");Фабрики объектов
class User
{
public static function createGuest()
{
return new self("Guest");
}
}Использование:
$user = User::createGuest();Общие настройки
class AppConfig
{
public static string $env = "production";
}Когда не стоит использовать static
Вместо обычных объектов
Плохо:
UserService::sendEmail();
UserService::save();
UserService::delete();Такой класс быстро превращается в набор глобальных функций.
Лучше:
$userService = new UserService();
$userService->sendEmail();Для зависимостей
Плохо:
class OrderService
{
public function create()
{
Database::save();
}
}Проблемы:
- сложно тестировать
- сильная связанность
- нельзя легко заменить зависимость
Лучше:
class OrderService
{
public function __construct(
private Database $db
) {}
}Static и Singleton
Часто static используют для создания Singleton:
class Database
{
private static ?Database $instance = null;
public static function getInstance()
{
if (!self::$instance) {
self::$instance = new Database();
}
return self::$instance;
}
}Но в современных приложениях чаще используют Dependency Injection, а не глобальные статические объекты.
Static vs объект
| Static | Обычный объект | |
|---|---|---|
| Создание через | Class::method() | new Class() |
Есть $this | ❌ | ✅ |
| Свои данные у каждого экземпляра | ❌ | ✅ |
| Общие данные | ✅ | ❌ |
| Легко тестировать | хуже | лучше |
| Подходит для сервисов | редко | чаще |
🎯 Вывод
staticпринадлежит классу, а не объекту- статические свойства общие для всех экземпляров
- статические методы вызываются через
Class::method() - внутри static-методов нельзя использовать
$this self::используется для обращения к текущему классуstatic::позволяет использовать позднее связывание- статические методы подходят для утилит и фабрик
- не стоит строить всю архитектуру на
static, лучше использовать объекты и Dependency Injection