Menu

PHP static: статические методы, свойства, self и static

Метод или свойство static принадлежит классу, а не объекту: метод вызывается через ClassName::method(), свойство читается через ClassName::$count, и new не нужен. self:: и static:: (позднее статическое связывание), new static, статические переменные в функциях и когда static это неправильный инструмент.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Метод или свойство static принадлежит самому классу, а не какому-либо объекту. Статический метод вызывается через ClassName::method(), а статическое свойство читается через ClassName::$property, без предварительного создания объекта. Внутри класса к тем же членам обращаются через self::.

Нигде нет new Temperature(). Статические члены полезны для вспомогательных функций, которым не нужно состояние объекта (преобразования, фабрики, проверки), и для данных, которые принадлежат классу целиком, например счётчика.

Статические свойства общие для всех объектов

У обычного свойства по одному значению на объект. У статического свойства одно значение на весь класс, поэтому каждый объект видит одно и то же. Здесь каждый новый User увеличивает общий счётчик и получает следующий ID:

Обратите внимание на $ в self::$nextId: статические свойства сохраняют его после ::, а константы (self::MAX) нет. Статическое свойство живёт только в пределах одного запроса PHP. На типичном сайте (PHP-FPM или Apache) оно начинается заново при каждой загрузке страницы, поэтому хранить в нём данные между посетителями нельзя.

У статических методов нет $this

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

Обратное направление допустимо: обычный метод может вызывать статические, как withSeparator() делает с self::make().

self и static: позднее статическое связывание

self:: указывает на класс, в котором написан код. static:: указывает на класс, для которого метод вызван во время выполнения. Разница проявляется только при наследовании, и важнее всего она для фабричных методов:

Post::createWithSelf() возвращает Model, а это почти никогда не то, что нужно вызывающему коду. static указывает на Post, потому что именно этот класс назван в вызове; PHP называет это поздним статическим связыванием. Используйте static:: и new static() в методах, которые предназначены для наследования, и self::, когда имеете в виду именно этот класс. То же правило работает для констант: static::TABLE берёт собственную TABLE дочернего класса, а self::TABLE всегда читает константу из класса, где написан код.

Унаследованные статические свойства общие

Дочерний класс разделяет статическое свойство родителя, если не объявит своё. Это классический сюрприз со static: два подкласса считают в одно число.

У Apples нет своего $count, поэтому Apples::$count это Counter::$count, и оба выводят 2. Pears переобъявляет свойство и считает отдельно. Статическое свойство, объявленное в трейте, ведёт себя иначе: каждый класс, использующий трейт, получает отдельную копию.

Статические переменные внутри функций

У static внутри тела функции есть второй смысл: статическая переменная сохраняет значение между вызовами. Начальное значение присваивается только при первом выполнении функции:

Второй slowSquare(12) пропускает вычисление. Как и статические свойства, эти значения сбрасываются в конце каждого запроса. Область видимости переменных в целом описана на странице о переменных.

Когда static это неправильный выбор

Статические методы удобны, и поэтому ими легко злоупотребить. Класс, все методы которого читают и пишут статические свойства, это глобальное состояние с именем класса: его разделяют все вызывающие, тесты не могут получить свежую копию, и подменить реализацию нельзя.

Хорошие применения static: чистые вспомогательные функции без состояния (Slug::make()), именованные конструкторы (Color::fromHex()) и константы на уровне класса. Если методу нужны данные, которые могут различаться между двумя использованиями, ему нужен объект.

Часто задаваемые вопросы

Как вызвать статический метод в PHP?

Через имя класса и ::: MathHelper::square(4). Внутри того же класса используйте self::square(4) или static::square(4). Объект не нужен, а внутри статического метода нет $this.

Чем self отличается от static в PHP?

self:: всегда означает класс, в котором написан код. static:: означает класс, для которого метод на самом деле вызван, а это может быть дочерний класс; это называется поздним статическим связыванием. Поэтому в методе родителя create() new self() всегда строит родителя, а new static() строит тот дочерний класс, который его вызвал.

Что такое статическое свойство в PHP?

Свойство, объявленное как public static int $count = 0;, принадлежит классу, поэтому у него одно значение на все объекты этого класса (и его потомков, если потомок его не переобъявил). Читайте и записывайте его через ClassName::$count или self::$count; обратите внимание на $.

Можно ли вызвать статический метод у объекта в PHP?

Да. $obj->square(4) и $obj::square(4) оба вызывают статический метод класса объекта, но $this внутри по-прежнему нет. Не работает обратное направление: вызов нестатического метода как ClassName::method() начиная с PHP 8 выбрасывает Error.

Можно ли использовать $this в статическом методе?

Нет. Статический метод выполняется без объекта, поэтому $this там не определён, и его использование выбрасывает Error ("Using $this when not in object context"). Чтобы обратиться к другим статическим членам, используйте self:: или static::.

Иллюстрация языков программирования Coddy

Учитесь программировать с Coddy

НАЧАТЬ