W3docs

static

В PHP ключевое слово static определяет свойства и методы уровня класса, доступные без создания экземпляра, а также сохраняет локальные переменные.

Ключевое слово static в PHP

Ключевое слово static в PHP имеет два принципиально разных применения, и с самого начала полезно разграничить их:

  1. Члены классаstatic обозначает свойство или метод, принадлежащие самому классу, а не отдельному объекту. Доступ к ним осуществляется без создания экземпляра, и все экземпляры разделяют одно и то же значение.
  2. Статические локальные переменные — внутри функции static заставляет локальную переменную сохранять своё значение между вызовами вместо того, чтобы сбрасываться каждый раз.

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

Статические члены класса

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

Базовый синтаксис

<?php

class MyClass {
  public static $myProperty = "Hello, world!";

  public static function myMethod() {
    return self::$myProperty;
  }
}

Обращение к статическому члену выполняется через оператор разрешения области видимости ::, а не через объектный оператор ->:

<?php

echo MyClass::$myProperty;   // Hello, world!
echo MyClass::myMethod();    // Hello, world!

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

Для подробного ознакомления смотрите Статические свойства и Статические методы.

Статические локальные переменные

Это же ключевое слово делает совершенно другое внутри функции: оно заставляет переменную сохраняться между вызовами. Без static локальная переменная переинициализируется при каждом вызове; с ним начальное значение устанавливается один раз, а переменная сохраняет то, что содержала в прошлый раз.

<?php

function counter() {
  static $count = 0;   // initialised only on the first call
  $count++;
  return $count;
}

echo counter(); // 1
echo counter(); // 2
echo counter(); // 3

Это удобно для кэширования дорогостоящего результата или подсчёта количества вызовов функции — без утечки глобальной переменной.

Примеры

Рассмотрим несколько практических примеров статических членов класса:

Примеры использования ключевого слова static в PHP

<?php

// Example 1
class Counter
{
  public static $count = 0;

  public static function increment()
  {
    self::$count++;
  }
}

Counter::increment();
Counter::increment();
echo Counter::$count . PHP_EOL;

// Example 2
class User
{
  public static $name;

  public static function setName($name)
  {
    self::$name = $name;
  }
}

User::setName("John Doe");
echo User::$name;

В Counter статическое свойство $count является общим, поэтому два вызова increment() накапливают значение до 2. В User метод setName() сохраняет данные в самом классе, а не в каком-либо объекте.

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

При обращении к статическому члену из метода есть два варианта, и разница имеет значение в контексте наследования:

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

class Base {
  public static function create() {
    return new static();   // runtime class
  }
  public static function createSelf() {
    return new self();     // always Base
  }
}

class Child extends Base {}

echo get_class(Child::create());     // Child
echo "\n";
echo get_class(Child::createSelf()); // Base

Используйте static::, когда подкласс должен иметь возможность переопределить поведение или быть инстанцированным — приведённый выше шаблон является основой фабричных методов. Используйте self::, когда вы намеренно имеете в виду этот класс. Для вызова статического метода родителя используйте parent::. Смотрите Наследование для более широкого контекста.

Типичные сценарии использования

  • Счётчики и общее состояние — единственное значение, отслеживаемое по всем экземплярам, как в примере с Counter.
  • Утилиты и вспомогательные методы — не имеющие состояния функции, сгруппированные под классом, например Math::clamp(), вызываемые без объекта.
  • Фабричные методыUser::fromArray($data) возвращает настроенный экземпляр; new static() сохраняет совместимость с подклассами.
  • Синглтоны и простые кэши — статическое свойство хранит единственный экземпляр или мемоизированный результат.

Для именованных неизменяемых общих значений предпочтите константу класса вместо статического свойства.

Подводные камни

  • Нет $this в статических методах. Статический метод может быть вызван без объекта, поэтому $this там не определён. Обращение к состоянию экземпляра из статического метода — признак неудачного проектирования.
  • Статические свойства — это квазиглобальное общее состояние. Поскольку все экземпляры разделяют одну копию, изменение её из любого места влияет на всех — это легко ведёт к скрытым зависимостям и нарушению изоляции тестов. Используйте осознанно.
  • :: для статики, -> для экземпляров. MyClass::$prop (статическое) против $obj->prop (экземпляра). Обратите внимание, что $ остаётся при имени свойства в статической форме: Counter::$count, а не Counter::count.
  • Статические локальные переменные принадлежат функции, а не вызову. Два рекурсивных вызова разделяют одну и ту же переменную static, что иногда может удивить.

Заключение

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

Практика

Практика
Что означает термин 'static'?
Что означает термин 'static'?
Was this page helpful?