Backend Development

PHP 8.1 Readonly Properties and Const

PHP 8.1 Readonly Properties and Const

A new keyword readonly introduced in PHP 8.1 allows to declare a property as readonly using the readonly keyword.

 

 

 

The Readonly class properties feature in PHP 8.1 marks a property as readonly using A new keyword “readonly“. A class property declared as readonly can be initialized once and further changes to this property is not permitted. For this reason readonly properties can be used in cases you need to prevent write access to certain properties directly.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Post
{
public readonly int $sid;
public function __construct(int $sid)
{
$this->sid = $sid;
}
}
$post = new Post(199);
echo $post->sid;
class Post { public readonly int $sid; public function __construct(int $sid) { $this->sid = $sid; } } $post = new Post(199); echo $post->sid;
class Post
{
    public readonly int $sid;

    public function __construct(int $sid)
    {
    	$this->sid = $sid;
    }
}

$post = new Post(199);
echo $post->sid;

As you see we marked the property $sid as readyonly. Note that readonly properties applies only to typed properties. Any attempt to declare a non typed property as readonly will show an error like so:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public readonly $sid;
public readonly $sid;
public readonly $sid;
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Fatal error: Readonly property Post::$sid must have type in .....
Fatal error: Readonly property Post::$sid must have type in .....
Fatal error: Readonly property Post::$sid must have type in .....

Another aspect is that we can’t set a readyonly property directly. To set a readonly property from the class itself using the constructor as in this example or from another method:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Post
{
public readonly int $sid;
public function setSid($sid)
{
$this->sid = $sid;
}
}
$post = new Post();
$post->setSid(200);
class Post { public readonly int $sid; public function setSid($sid) { $this->sid = $sid; } } $post = new Post(); $post->setSid(200);
class Post
{
    public readonly int $sid;

    public function setSid($sid)
    {
    	$this->sid = $sid;
    }
}

$post = new Post();

$post->setSid(200);

Here in this example i added a method to set the readonly property $sid. If you attempt to initialize the the readonly propety $sid more than once it show an error:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$post = new Post();
$post->setSid(200);
$post->setSid(300);
$post = new Post(); $post->setSid(200); $post->setSid(300);
$post = new Post();

$post->setSid(200);
$post->setSid(300);
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Fatal error: Uncaught Error: Cannot modify readonly property Post::$sid in ....
Fatal error: Uncaught Error: Cannot modify readonly property Post::$sid in ....
Fatal error: Uncaught Error: Cannot modify readonly property Post::$sid in ....

 

Also you can’t initialize a readonly property outside the scope of the class otherwise an error will be thrown:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$post = new Post();
$post->sid = 150;
echo $post->sid;
$post = new Post(); $post->sid = 150; echo $post->sid;
$post = new Post();
$post->sid = 150;
echo $post->sid;
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Fatal error: Uncaught Error: Cannot initialize readonly property Post::$sid from global scope in ....
Fatal error: Uncaught Error: Cannot initialize readonly property Post::$sid from global scope in ....
Fatal error: Uncaught Error: Cannot initialize readonly property Post::$sid from global scope in ....

Here setting the property directly show error although the property marked as public. 

 

Readonly Property and unset()

The php unset() function can not be used alongside with readonly property to unset the property:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$post = new Post();
unset($post->sid);
$post = new Post(); unset($post->sid);
$post = new Post();
unset($post->sid);
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Fatal error: Uncaught Error: Cannot unset readonly property Post::$sid from global scope in ...
Fatal error: Uncaught Error: Cannot unset readonly property Post::$sid from global scope in ...
Fatal error: Uncaught Error: Cannot unset readonly property Post::$sid from global scope in ...

 

Readonly Property and promoted constructors

If you remember the promoted constructor feature in PHP 8.0 which allows property declaration and class assignment be done through the constructor itself.

Example:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Post
{
public int $sid;
public function __construct(int $sid)
{
$this->sid = $sid;
}
}
class Post { public int $sid; public function __construct(int $sid) { $this->sid = $sid; } }
class Post
{
    public int $sid;

    public function __construct(int $sid)
    {
    	$this->sid = $sid;
    }
}

Which is equivalent to

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Post
{
public function __construct(public int $sid)
{}
}
class Post { public function __construct(public int $sid) {} }
class Post
{
    public function __construct(public int $sid)
    {}
}

Now we can use the readonly property alongside the promoted constructors like so:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Post
{
public function __construct(public readonly int $sid)
{}
}
$post = new Post(122);
echo $post->sid;
class Post { public function __construct(public readonly int $sid) {} } $post = new Post(122); echo $post->sid;
class Post
{
    public function __construct(public readonly int $sid)
    {}
}


$post = new Post(122);
echo $post->sid;

 

Readonly Vs Const

PHP OOP already includes the const keyword which may seem to serve a similar purpose like readonly, however there are many differences between the functionalities of the two keywords:

  • Class constant must have a default value
  • Can’t set class constant at runtime inside the constructor or from another method in contrast to readonly property. 
  • Class constant allocated once per class and not per class instance.
  • Class constant referenced inside the class using class name or the “self” keyword.
  • Class constant referenced outside the class using class name.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Post
{
public const sid=20;
}
echo Post::sid;
class Post { public const sid=20; } echo Post::sid;
class Post
{
    public const sid=20;
}

echo Post::sid;

Attempting to set  a class constant will raise an error:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Post
{
public const sid=20;
public function __construct(int $sid)
{
self::sid = $sid; // invalid
}
}
//
Parse error: syntax error, unexpected token "=" in ...
class Post { public const sid=20; public function __construct(int $sid) { self::sid = $sid; // invalid } } // Parse error: syntax error, unexpected token "=" in ...
class Post
{
    public const sid=20;

    public function __construct(int $sid)
    {
    	self::sid = $sid;                            // invalid 
    }
}

//
Parse error: syntax error, unexpected token "=" in ...

So a class constant supposed to have a predefined value set in the declaration step of this constant and can’t be changed afterwards.

 

0 0 votes
Article Rating

What's your reaction?

Excited
1
Happy
0
Not Sure
0
Confused
0

You may also like

Subscribe
Notify of
guest


0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments