← Назад к вопросам

Что за модификатор доступа readonly?

1.8 Middle🔥 141 комментариев
#PHP Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Модификатор доступа readonly в PHP

readonly — это модификатор доступа для свойств классов, появившийся в PHP 8.1. Он позволяет объявлять свойства, которые могут быть инициализированы только один раз — либо при объявлении, либо в конструкторе класса. После инициализации значение такого свойства не может быть изменено.

Ключевые особенности readonly-свойств

  1. Однократная инициализация: Значение может быть установлено только один раз
  2. Запрет модификации: После инициализации свойство становится неизменяемым
  3. Работа с объектами: Для readonly-свойств объектного типа действуют особые правила
  4. Наследование: Readonly-свойства могут наследоваться с определёнными ограничениями

Базовый пример использования

class User {
    public readonly int $id;
    public readonly string $username;
    
    public function __construct(int $id, string $username) {
        // Инициализация в конструкторе
        $this->id = $id;
        $this->username = $username;
    }
}

$user = new User(1, 'john_doe');
echo $user->id; // 1
echo $user->username; // john_doe

// Попытка изменить вызовет ошибку:
// $user->id = 2; // Fatal error: Uncaught Error: Cannot modify readonly property

Инициализация при объявлении

class Configuration {
    public readonly string $environment = 'production';
    
    public function __construct() {
        // Можно не инициализировать в конструкторе,
        // если значение задано при объявлении
    }
}

Особенности работы с объектами

Для свойств объектного типа readonly предотвращает переназначение, но не модификацию внутреннего состояния объекта:

class Address {
    public function __construct(public string $city) {}
}

class User {
    public readonly Address $address;
    
    public function __construct(Address $address) {
        $this->address = $address;
    }
}

$address = new Address('Moscow');
$user = new User($address);

// Это вызовет ошибку - нельзя переназначить свойство:
// $user->address = new Address('Saint Petersburg');

// Но можно изменить внутреннее состояние объекта:
$user->address->city = 'Saint Petersburg'; // Работает!
echo $user->address->city; // Saint Petersburg

Ограничения и правила

  1. Только для типизированных свойств: Readonly можно применять только к свойствам с явно указанным типом
  2. Нельзя применять к статическим свойствам: public static readonly — недопустимо
  3. Инициализация обязательна: Свойство должно быть инициализировано до окончания работы конструктора
  4. Неявная инициализация невозможна: Нельзя использовать методы, отличные от конструктора

Некорректный пример:

class Example {
    public readonly int $value;
    
    public function setValue(int $val) {
        $this->value = $val; // Ошибка: нельзя инициализировать вне конструктора
    }
}

Наследование readonly-свойств

class Base {
    public readonly int $baseValue;
    
    public function __construct(int $value) {
        $this->baseValue = $value;
    }
}

class Derived extends Base {
    public readonly int $derivedValue;
    
    public function __construct(int $baseVal, int $derivedVal) {
        parent::__construct($baseVal);
        $this->derivedValue = $derivedVal;
    }
}

Практическое применение

DTO (Data Transfer Objects):

class UserDTO {
    public function __construct(
        public readonly int $id,
        public readonly string $name,
        public readonly DateTimeImmutable $createdAt
    ) {}
}

// Иммутабельный объект для передачи данных
$user = new UserDTO(1, 'Alice', new DateTimeImmutable());

Конфигурационные объекты:

class AppConfig {
    public function __construct(
        public readonly string $databaseHost,
        public readonly string $databaseName,
        public readonly int $cacheTtl
    ) {}
}

Преимущества использования readonly

  1. Безопасность: Предотвращает случайное изменение важных данных
  2. Ясность кода: Чётко указывает на иммутабельность свойства
  3. Потокобезопасность: Readonly-объекты безопасны в многопоточных средах
  4. Предсказуемость: Гарантирует, что состояние объекта не изменится после создания

Отличия от const

Важно не путать readonly с константами:

  • const: Значение должно быть известно на этапе компиляции, принадлежит классу
  • readonly: Значение определяется в runtime, принадлежит экземпляру класса
class Example {
    public const VERSION = '1.0'; // Константа класса
    public readonly string $id;   // Свойство экземпляра
}

Модификатор readonly значительно улучшает возможности создания иммутабельных объектов в PHP, что особенно важно для DTO, value-объектов и конфигурационных структур, обеспечивая лучшую предсказуемость и надёжность кода.

Что за модификатор доступа readonly? | PrepBro