W3docs

PHP OOP: понимание статических методов

Статические методы PHP: определение и вызов, self:: vs static:: (позднее статическое связывание), счётчики, фабричные методы и подводные камни.

Статический метод — это метод, объявленный с ключевым словом static, который принадлежит самому классу, а не какому-либо конкретному объекту, созданному из него. Поскольку он привязан к классу, его можно вызывать напрямую через имя класса и оператор разрешения области видимости (::) — без new.

В этой главе показано, как определять и вызывать статические методы, чем они отличаются от обычных (экземплярных) методов, как ведут себя self:: и static:: внутри них, а также паттерны, где статические методы действительно полезны (утилиты, счётчики и фабричные методы). Если вы только знакомитесь с классами, сначала прочитайте Классы и объекты PHP.

Что такое статические методы в PHP?

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

Это делает статические методы естественным выбором для операций без состояния: вычислений, зависящих только от входных данных, а не от состояния конкретного объекта. Классический пример — вычисление среднего значения списка чисел.

class Math
{
    public static function average(array $numbers): float
    {
        return array_sum($numbers) / count($numbers);
    }
}

Зачем использовать статические методы?

ПричинаЧто это означает на практике
Отсутствие состоянияРезультат зависит только от аргументов, поэтому он предсказуем и легко тестируем.
Без создания экземпляраВы пропускаете new ClassName() — удобно для вспомогательных/утилитных функций.
Общее состояниеСтатические методы могут читать и обновлять статические свойства, позволяя классу отслеживать данные для всех его объектов (например, счётчик).
Фабричные методыСтатический метод может создать и вернуть настроенный экземпляр, давая более понятную альтернативу сложному конструктору.

Компромисс: поскольку статические методы нельзя переопределить через обычную ссылку на объект и они не несут состояния экземпляра, их избыточное использование затрудняет создание моков и модульное тестирование. Предпочитайте методы экземпляра, когда поведение зависит от состояния объекта.

Как определить и вызвать статический метод

Добавьте static перед именем метода, затем вызовите его через ClassName::method():

<?php

class Math
{
    public static function average(array $numbers): float
    {
        return array_sum($numbers) / count($numbers);
    }
}

$average = Math::average([1, 2, 3, 4, 5]);
echo $average; // 3

Токен :: — это оператор разрешения области видимости — тот же оператор, который используется для констант класса.

«Попробуйте сами» недоступно для этого примера.

self:: vs static:: и отсутствие $this

Внутри статического метода нельзя использовать $this, потому что нет экземпляра, на который можно сослаться. Чтобы обратиться к другому статическому члену класса, используйте self:: или static::.

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

class Base
{
    public static function create(): string
    {
        return self::class;   // always "Base"
    }

    public static function make(): string
    {
        return static::class; // the called class
    }
}

class Child extends Base {}

echo Base::create(), "\n";  // Base
echo Child::create(), "\n"; // Base   (self:: is fixed to where it's written)
echo Child::make(), "\n";   // Child  (static:: follows the call)

Используйте static::, когда родительский класс определяет поведение, которое подклассы должны уметь перенаправить на себя — это основа фабричного паттерна, описанного ниже. Подробнее в Наследовании PHP.

Статические методы со статическими свойствами: счётчик

Статические методы часто используются совместно со статическими свойствами для хранения состояния, разделяемого между всеми объектами класса.

<?php

class User
{
    public static int $count = 0;

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

    public static function total(): int
    {
        return self::$count;
    }
}

new User('Ada');
new User('Linus');

echo User::total(); // 2

Обратите внимание: total() читает self::$count без объекта — свойство хранится в классе, а не в конкретном User.

Фабричные методы

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

<?php

class Temperature
{
    private function __construct(private float $celsius) {}

    public static function fromCelsius(float $c): static
    {
        return new static($c);
    }

    public static function fromFahrenheit(float $f): static
    {
        return new static(($f - 32) * 5 / 9);
    }

    public function celsius(): float
    {
        return $this->celsius;
    }
}

$t = Temperature::fromFahrenheit(212);
echo $t->celsius(); // 100

Использование new static() (позднее статическое связывание) означает, что подкласс, вызывающий fromCelsius(), получит экземпляр себя, а не Temperature.

Частые подводные камни

  • $this недоступен. Его использование внутри статического метода вызывает фатальную ошибку — нет текущего объекта.
  • Статические и экземплярные методы могут иметь одинаковое имя только в разных классах, но не в одном. Внутри класса каждое имя метода уникально.
  • Статический метод можно вызвать на объекте ($obj::method() или даже $obj->method()), но он всё равно выполнится без $this. Вызов через $obj-> допустим, но вводит в заблуждение — предпочитайте ClassName::method() для ясности.
  • Статическое состояние глобально для процесса. Статический счётчик разделяется между всеми экземплярами и сохраняется на протяжении всего запроса, что может удивить в длительно работающем или тестовом коде.

Заключение

Статические методы принадлежат классу, выполняются без экземпляра и не имеют доступа к $this. Они хорошо подходят для утилит без состояния, общего состояния класса через статические свойства и фабричных методов для создания настроенных объектов. Используйте self::, когда имеете в виду определяющий класс, и static::, когда подклассы должны уметь перенаправить вызов на себя. Выбирайте статические методы, когда поведение привязано к классу, а не к конкретному объекту — и предпочитайте методы экземпляра в противном случае.

Далее углубите понимание с помощью Статических свойств PHP и Констант класса PHP.

Практика

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