Readonly Properties (PHP 8.1)
Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 19 of 91.
PHP 8.1 introduced readonly properties, which can only be assigned once and cannot be modified afterward. Unlike constants, readonly properties are set during object initialization rather than at class definition time.
You declare a readonly property by adding the readonly keyword before the type declaration:
<?php
class User {
public readonly string $id;
public readonly string $name;
public function __construct(string $id, string $name) {
$this->id = $id;
$this->name = $name;
}
}
$user = new User("U001", "Alice");
echo $user->id . "\n";
echo $user->name;
Output:
U001
AliceOnce assigned, attempting to change a readonly property will cause an error. This makes them perfect for values that should remain constant throughout an object's lifetime, like IDs or creation timestamps.
Readonly properties must have a type declaration and can only be initialized once, either in the constructor or at the point of declaration. They work with any visibility modifier:
<?php
class Product {
public function __construct(
public readonly string $sku,
private readonly float $cost
) {}
public function getCost(): float {
return $this->cost;
}
}
$product = new Product("ABC123", 29.99);
echo $product->sku;
Output:
ABC123Key Point: Readonly properties provide immutability at the property level. They're ideal for data that identifies an object or shouldn't change after creation, combining the flexibility of runtime initialization with the safety of preventing accidental modifications.
Challenge
EasyLet's build an immutable configuration system that uses readonly properties to ensure critical settings cannot be accidentally changed after initialization.
You'll create two files that work together to manage application configuration:
Config.php— Define aConfigclass that represents application configuration with immutable settings. The class should have three public readonly properties:string $appName,string $version, andint $maxConnections. Use constructor promotion to declare and initialize all three readonly properties in a single, clean constructor definition. Add agetInfo()method that returns a string in the format"[appName] v[version] (max: [maxConnections] connections)".main.php— Include the Config class file. You will receive three inputs: the app name, version, and maximum connections (as a string that needs to be converted to an integer). Create aConfigobject using these values. Print the result ofgetInfo()on the first line. Then print each readonly property on its own line by accessing them directly: the app name, the version, and the max connections.
The readonly properties ensure that once a configuration is created, its values are locked in place — perfect for settings that should remain constant throughout your application's runtime. Notice how constructor promotion combined with readonly creates a very concise way to define immutable value objects.
Your output should display the formatted info string followed by each individual property value, demonstrating that readonly properties can still be read from outside the class.
Cheat sheet
PHP 8.1 introduced readonly properties, which can only be assigned once and cannot be modified afterward:
<?php
class User {
public readonly string $id;
public readonly string $name;
public function __construct(string $id, string $name) {
$this->id = $id;
$this->name = $name;
}
}
$user = new User("U001", "Alice");
echo $user->id; // U001
Readonly properties must have a type declaration and can only be initialized once. They work with any visibility modifier and can be combined with constructor promotion:
<?php
class Product {
public function __construct(
public readonly string $sku,
private readonly float $cost
) {}
}
$product = new Product("ABC123", 29.99);
echo $product->sku; // ABC123
Readonly properties are ideal for values that should remain constant throughout an object's lifetime, like IDs, timestamps, or configuration settings.
Try it yourself
<?php
require_once 'Config.php';
// Read inputs
$appName = trim(fgets(STDIN));
$version = trim(fgets(STDIN));
$maxConnections = intval(trim(fgets(STDIN)));
// TODO: Create a Config object using the input values
// TODO: Print the result of getInfo()
// TODO: Print each readonly property on its own line:
// - app name
// - version
// - max connections
?>This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe $this KeywordMethodsPropertiesConstructor (__construct)Destructor (__destruct)Recap - Simple Calculator4Inheritance
Basic InheritanceThe parent:: KeywordMethod OverridingThe final KeywordAbstract ClassesRecap - Employee Hierarchy7Encapsulation
Public, Protected, PrivateAccess Modifiers in DepthGetters and SettersInformation HidingConstructor Promotion (8.0)Recap - Student Records System2Namespaces & Autoloading
Introduction to NamespacesThe use KeywordPSR-4 Autoloading StandardComposer AutoloaderRecap - Organized Project5Interfaces & Contracts
Introduction to InterfacesImplementing InterfacesMultiple Interface ImplementInterface vs Abstract ClassType Hinting with InterfacesRecap - Shape Calculator8Magic Methods
Magic Methods Introduction__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Object Cloning__serialize & __unserializeRecap - Custom Collection11Type System & Error Handling
Type DeclarationsNullable TypesUnion & Intersection TypesException ClassesCustom Exception HierarchyTry, Catch, FinallyRecap - Form Validator14Project: Library Management
Project OverviewBook and User Classes3Class Properties
Instance vs Static PropertiesConstants in ClassesStatic Methods & PropertiesPrivate & Protected PropertiesReadonly Properties (PHP 8.1)Recap - Bank Account Manager6Polymorphism
Method Overriding RevisitedPolymorphism via InterfacesType Hinting & Union TypesLate Static BindingRecap - Payment Processor9Traits
Introduction to TraitsUsing Multiple TraitsTrait Conflict ResolutionAbstract Methods in TraitsTraits vs Inheritance12Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern