Hello internals:
Currently, this is not allowed by PHP:
class Foo {
public function __construct(
public string &$ref { get => $this->ref ?? 'null'; set => $this->ref =
$value; }
) {}
}
$var = 'hello';
$foo = new Foo($var);
$var = "world";
echo $foo->ref;
https://3v4l.org/JRArK
Currently, you have to emulate it like so:
class Foo {
public string $ref {
get => $this->_ref;
set => $this->_ref = $value;
}
public function __construct(
private string &$_ref,
) {}
}
$var = 'hello';
$foo = new Foo($var);
$foo->ref = 'world';
echo $var;
https://3v4l.org/0cC0S
After the release, I'd like to propose an RFC that allows using references with
hooks:
A hooked reference variable is a callable/closure under the hood (technically,
a reference to the actual hook methods) that can be used like a value. Reading
from it calls the ::get() method, and setting to it calls the ::set($value)
method. If the callable were to be written in PHP, it might look something like
the following psuedo code:
function hookRef(...$args) use (&$backedValue) {
if(empty($args)) return $backedValue::get();
$backedValue = $backedValue::set(array_first($args));
}
In simplified terms, the engine, upon detecting a read/write to a hooked
reference (eg, a standalone variable pointing to a hooked property), instead of
doing typical variable access, it will call the bound closure with the
appropriate arguments. This will effectively allow hooks to be references.
This would also handle the case for arrays, which appears to require the same
plumbing to exist.
Downsides:
1. this will probably necessitate a new zval type, determined at runtime (it
will not be exposed to users).
2. there are a lot of ways to access/write to a variable (especially once you
consider arrays) thus it will touch a lot of the engine.
Thoughts? Concerns? Suggestions?
— Rob