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

Reply via email to