Re: [PHP-DEV] [RFC] Readonly Variables

Hello Kamil,

On 23. Feb 2026, at 22:58, Kamil Tekiela <tekiela246@gmail.com> wrote:

1. Why the use of readonly keyword? Why not const or some new keyword,
e.g. locked.

I spent a long time thinking about the right keyword. In an early stage of development I chose `const`, as it is already used in this way in JavaScript, for example. However, the further I developed the feature and the more feedback I gathered from others, the more I gravitated towards `readonly`. The `readonly` keyword is already used in PHP for class properties and serves exactly the same purpose: declaring variables as immutable. Reusing `readonly` for variables is therefore consistent with existing PHP semantics. The `const` keyword, on the other hand, has fundamentally different semantics in PHP. A `const` declaration at the top level defines a globally accessible constant, and inside a class it defines a class constant. This is quite different from a locally scoped immutable variable, and using const for this feature would likely cause confusion for PHP developers who are already familiar with its existing meaning. Introducing an entirely new keyword for this purpose, such as `locked`, would in my opinion be counterproductive, as it could be unintuitive for developers who are already familiar with `readonly` and its meaning in PHP.

2. Why does unset not remove the variable completely? If you want a
feature to only unlock the variable then it probably needs a new
keyword, e.g. unlock

Thank you for pointing that out, as I apparently expressed myself ambiguously in the RFC. `unset()` behaves exactly as it does for regular variables: it removes the variable entirely. The only additional effect is that the `readonly` flag is cleared along with it, meaning the variable name can subsequently be reused with a new assignment, without the `readonly` flag. I have updated the RFC to make this behavior more explicit.

Regarding the idea of a dedicated unlock mechanism: I don't think this is necessary, and I honestly don't see a practical use case for it. If a variable needs to be modified after its initial assignment, it simply should not be declared as readonly in the first place.

3. What exactly does this mean: "Readonly variables inside loops are
permitted but limited to a single declaration"? What does a single
declaration look like?

A readonly variable declared inside a loop is exposed to the outer scope, just like any other variable in PHP. This means that on the second iteration, PHP would attempt to re-assign an already initialized readonly variable, which results in a fatal error. A "single declaration" therefore means that the readonly variable can only be initialized once throughout the entire execution of the loop, not once per iteration.

I hope this clarifies the behavior. Please let me know if you have any further questions.

4. How will this impact optimizer and JIT?

Thank you for raising this point. I have not yet investigated the impact on the optimizer and JIT, as the current implementation is an initial proof of concept intended to gather feedback from the community. I will definitely look into this before the voting phase and investigate whether and how readonly variables can be leveraged for potential optimizations. I will report back with my findings.

5. You said that readonly variables cannot be used with the global
keyword. But what about readonly variables in global scope? Will they
still behave like a typical global variable?

I am not entirely sure what you mean by "typical global variable behavior", so I will try to address what I believe you are asking.
If your question is whether a readonly variable declared in the global scope can be imported into a function via the `global` statement, the answer is no. Importing a readonly variable via `global` is forbidden and results in an error.
If you are asking whether readonly variables declared in the global scope are automatically accessible in function scopes, the answer is also no. Readonly variables follow the same scoping rules as regular variables, meaning they are not automatically available inside functions, just as regular variables are not.
If you meant something else entirely, please feel free to clarify and I will be happy to address it.

6. What exactly counts as a variable declaration? When is it a valid
syntax to use this keyword? I don't think PHP had the concept of
variable declaration until now.

By "declaration" I simply mean a regular variable assignment prefixed with the readonly keyword:

<?php
readonly $foo = "bar”;

You are right that PHP has not had a formal concept of variable declaration until now. The readonly keyword in this context is purely a modifier on a standard assignment statement, signaling that the variable cannot be re-assigned after its initial value has been set. Any valid assignment expression can be used as the initial value, including object instantiation, function calls, or scalar values.

7. What about compound variables such as arrays and objects?

The behavior differs depending on the type of value assigned to a readonly variable.

For arrays, the entire array is immutable. This means that neither the array itself nor its elements can be modified after the initial assignment:

<?php
readonly $arr = [1, 2, 3];
$arr[] = 4; // Error: Cannot re-assign readonly variable
$arr[0] = 99; // Error: Cannot re-assign readonly variable

For objects, the behavior is consistent with how readonly works for class properties: the variable binding is immutable, meaning the object reference cannot be replaced with a different object. However, the internal state of the object itself can still be modified:

<?php
readonly $obj = new stdClass();
$obj->value = "changed"; // Valid: modifying the object's internal state is allowed
$obj = new stdClass(); // Error: Cannot re-assign readonly variable

I have added examples for both cases to the RFC to make this behavior explicit.

I would prefer starting with readonly parameters as I feel that would
bring the most value.

I find the idea of readonly parameters interesting and have already given it some thought. However, it is out of scope for this RFC, as I wanted to keep the initial proposal focused and manageable. I have already mentioned it in the Future Scope section of the RFC as a potential natural extension that could be addressed in a separate RFC in the future.

I think it would also be worthwhile to investigate a simpler syntax
for define().

It is worth noting that PHP already provides two ways to define global constants: `define()` and the `const` keyword. Both serve a different purpose than readonly variables, as they are globally accessible and not scoped to a local or functional context. See: Online PHP editor | output for 1r6gk

Cheers,
Joshua Rüsweg

On Tue, Feb 24, 2026, at 12:52 PM, Joshua Rüsweg wrote:

I would prefer starting with readonly parameters as I feel that would
bring the most value.

I find the idea of readonly parameters interesting and have already
given it some thought. However, it is out of scope for this RFC, as I
wanted to keep the initial proposal focused and manageable. I have
already mentioned it in the Future Scope section of the RFC as a
potential natural extension that could be addressed in a separate RFC
in the future.

A slight tangent here, but what would readonly parameters do?

If you pass something by value, then already you cannot modify the value in the caller. If the value is large, it's already kept efficient by copy-on-write.

If you pass by reference, then presumably you *want* to modify the value in the caller.

If the value is an object, then as already discussed, its internals are mutable either way so you gain little, but the function cannot change the identity in the caller anyway.

So I don't see what readonly parameters would even accomplish. The thing they accomplish in JS or Java or C simply doesn't apply in PHP.

I'm still undecided at the moment on readonly variables.

--Larry Garfield

Thanks for the replies.

> 3. What exactly does this mean: "Readonly variables inside loops are
> permitted but limited to a single declaration"? What does a single
> declaration look like?

A readonly variable declared inside a loop is exposed to the outer scope, just like any other variable in PHP. This means that on the second iteration, PHP would attempt to re-assign an already initialized readonly variable, which results in a fatal error. A "single declaration" therefore means that the readonly variable can only be initialized once throughout the entire execution of the loop, not once per iteration.

So does that mean that it can only be used within a loop if that loop
only has a single iteration or that the assignment is guarded by some
condition?

$var = null;
while(true) {
    if ($var === null) {
        readonly $var = 42;
    }
}

> 5. You said that readonly variables cannot be used with the global
> keyword. But what about readonly variables in global scope? Will they
> still behave like a typical global variable?

I am not entirely sure what you mean by "typical global variable behavior", so I will try to address what I believe you are asking.
If your question is whether a readonly variable declared in the global scope can be imported into a function via the `global` statement, the answer is no. Importing a readonly variable via `global` is forbidden and results in an error.
If you are asking whether readonly variables declared in the global scope are automatically accessible in function scopes, the answer is also no. Readonly variables follow the same scoping rules as regular variables, meaning they are not automatically available inside functions, just as regular variables are not.
If you meant something else entirely, please feel free to clarify and I will be happy to address it.

I meant using $GLOBALS.

readonly $var = 42;
function foo() {
    $GLOBALS['foo'] = 'bar';
}
foo();
var_dump($foo);

> 6. What exactly counts as a variable declaration? When is it a valid
> syntax to use this keyword? I don't think PHP had the concept of
> variable declaration until now.

By "declaration" I simply mean a regular variable assignment prefixed with the readonly keyword:

<?php
readonly $foo = "bar”;

You are right that PHP has not had a formal concept of variable declaration until now. The readonly keyword in this context is purely a modifier on a standard assignment statement, signaling that the variable cannot be re-assigned after its initial value has been set. Any valid assignment expression can be used as the initial value, including object instantiation, function calls, or scalar values.

Right, but if PHP users have never thought about variable declaration,
then it might be confusing for them to understand when it is legal to
use this keyword. For example, you said that array destructuring is
not supported but for me it's a regular variable assignment. It seems
that assignment within a loop is also not allowed, but that doesn't
seem to be clearly specified in the RFC.

while(readonly $arr = $pdoStmt->fetch()) {} // Is this allowed
assuming it only iterates once?
foreach($arr as readonly $element) {} // This is forbidden, correct?
for(readonly $foo; ; ) {} // Is this allowed?
if(readonly $val = foobar()) {} // This is a regular variable
assignment, is this allowed?

What about array vivification?

readonly $arr[] = 42;

Or a declaration with a warning:

readonly $i++;

What about a slightly more complex variable assignment?

$arr = [readonly $var = 42];
// or
readonly $var1 = $var2 = 42;
// or
foobar(readonly $baz = 42);
// or
$foo = 'bar';
readonly $$foo = 42;

Regards,
Kamil