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

Сегодня мы поговорим о статических свойствах и методах в PHP. Если коротко – то это свойства и методы, которые принадлежат классу целиком, а не созданным объектам этого класса. То есть использовать их можно даже без создания объектов. Иногда их называют просто свойствами и методами класса. Не путайте их со свойствами и методами объектов, которые мы изучали ранее!

Определяются статические свойства и методы с помощью ключевого свойства static.

Статические методы

Давайте рассмотрим самый простой пример статического метода.

class A {
    public static function test(int $x)
    {
        return 'x = ' . $x;
    }
}

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

echo A::test(5);

Результат:

x = 5

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

class User
{
    private $role;

    private $name;

    public function __construct(string $role, string $name)
    {
        $this->role = $role;
        $this->name = $name;
    }
}

Мы с помощью конструктора можем создавать пользователей с разными ролями (модератор, администратор, простой пользователь) и именами.

Чтобы создать администратора, нам нужно сделать следующее:

$admin = new User('admin', 'Иван');

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

class User
{
    private $role;

    private $name;

    public function __construct(string $role, string $name)
    {
        $this->role = $role;
        $this->name = $name;
    }

    public static function createAdmin(string $name)
    {
        return new self('admin', $name);
    }
}

Этот метод возвращает новый объект текущего класса (благодаря слову self), и передаёт ему всегда в аргумент $role значение ‘admin’. Использование такого метода будет выглядеть следующим образом.

$admin = User::createAdmin('Иван');
var_dump($admin);

Вывод будет следующим:

object(User)[1]
  private 'role' => string 'admin' (length=5)
  private 'name' => string 'Иван' (length=8)

Всё у нас успешно сработало. В данном упрощенном примере, может показаться, что такой метод мало чем полезен, однако представьте, как будет удобно, если таких параметров в конструкторе будет 5, и из них 4 можно будет сделать для какого-то рода объектов всегда одинаковыми. В таком случае статический метод, порождающий объекты, становится изящным способом упростить код.

Отличие от методов объектов

В отличие от методов объектов, в статических методах нет слова $this – оно указывает только на текущий объект. Если объекта нет – нет и $this!

Статические свойства

А что на счёт статических свойств? Для чего можно использовать их?
Давайте создадим класс со статическим свойством:

class A
{
    public static $x;
}

Мы можем читать и писать в это свойство, не создавая объектов этого класса:

A::$x = 5;
var_dump(A::$x); // 5

Кроме того, эти же свойства будут доступны и у объектов этого класса:

A::$x = 5;
$a = new A();
var_dump($a::$x); // 5

И даже внутри этих объектов мы сможем достучаться до этих свойств, при помощи слова self::

class A
{
    public static $x;

    public function getX()
    {
        return self::$x;
    }
}

A::$x = 5;
$a = new A();
var_dump($a->getX()); // 5

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

class A
{
    public static $x;

    public static function getX()
    {
        return self::$x;
    }
}

A::$x = 5;
$a = new A();
var_dump($a::getX());

Применение статических свойств

Порой приходится в классе хранить информацию, которая будет использоваться всеми объектами, или будет говорить что-то общее обо всех объектах. Например, можно сделать счётчик созданных объектов внутри класса. Давайте создадим в классе Human статическую переменную $count, и сделаем её приватной, чтобы изменять её можно было только внутри класса. И давайте сразу сделаем для неё геттер.

class Human
{
    private static $count = 0;

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

Давайте выведем значение этой переменной.

echo 'Людей уже ' . Human::getCount(); // 0

Что нужно сделать, чтобы при создании нового объекта класса Human, это число увеличивалось? Правильно, просто увеличивать это значение в конструкторе – он ведь вызывается каждый раз при создании объекта.

class Human
{
    private static $count = 0;

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

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

Давайте проверим, что всё работает:

$human1 = new Human();
$human2 = new Human();
$human3 = new Human();
echo 'Людей уже ' . Human::getCount(); // 3

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

loader
Логические задачи с собеседований