🧱 Суть

Статические свойства и методы (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 context

self:: 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

🔗 Связано