3v4l.org

run code in 300+ PHP versions simultaneously
<?php class Reference { private static $DATA = []; private $index = 0; public function __construct($value) { // cannot create a reference of a reference if ($value instanceof self) { $this->index = $value->index; } else { $this->index = count(self::$DATA); self::$DATA[$this->index] = $value; } } public function get() { return self::$DATA[$this->index]; } public function set($value) { self::$DATA[$this->index] = $value; } } $x = [1, 2, 3]; // foreach($x as &$ref) { ... } /* $x[0] */ $x[0] = new Reference($x[0]); // Reference#0(index 0) = 1 $ref = clone $x[0]; // Reference#1(index 0) $ref->set($ref->get() + 100); // set index 0 = 101 /* $x[1] */ $x[1] = new Reference($x[1]); // Reference#2(index 1) = 2 $ref = clone $x[1]; // Reference#3(index 1) $x[0] = $x[0]->get(); // without $ref, $x[0] is the only reference to its value and demoted back to a value $ref->set($ref->get() + 100); // set index 1 = 101 /* $x[2] */ $x[2] = new Reference($x[2]); // Reference#4(index 2) = 3 $ref = clone $x[2]; // Reference#5(index 2) $x[1] = $x[1]->get(); // demoted $ref->set($ref->get() + 100); // set index 2 = 103 // end foreach /* $x is [101, 102, Reference#4(index 2)] */ /* $ref remains as Reference#5(index 2) */ $b = $x; // $b[0] = clone $x[0]; - except $x[0] is an integer so this was automatic // $b[1] = clone $x[1]; - same $b[2] = clone $x[2]; // creating a copy of what was in $x[2] /* $b is [101, 102, Reference#6(index 2)] - a different Reference as $x[2] and $ref but the same underlying value */ $b[0] = 0; // foreach($x as &$ref) { ... } /* $x[0] */ $x[0] = new Reference($x[0]); // Reference#7(index 3) = 101 $ref = clone $x[0]; // Reference#8(index 3) $ref->set($ref->get() + 100); // set index 3 = 201 /* $x[1] */ $x[1] = new Reference($x[1]); // Reference#9(index 4) = 102 $ref = clone $x[1]; // Reference#10(index 4) $x[0] = $x[0]->get(); // demoted $ref->set($ref->get() + 100); // set index 4 = 202 /* $x[2] */ // $x[2] = new Reference($x[2]); // - except $x[2] is already Reference#4(index 2) $ref = clone $x[2]; // Reference#11(index 2) $x[1] = $x[1]->get(); // demoted $ref->set($ref->get() + 100); // set index 2 = 203 // end foreach /* $x is [201, 202, Reference#4(index 2)] */ /* $ref remains as Reference#11(index 2) */ /* $b was not modified during the foreach and still contains [0, 102, Reference#6(index 2)] */ /* however the underlying value of the Reference did change */ // var_dump($b); var_dump([$b[0], $b[1], $b[2]->get()]);
Output for 5.5.0 - 5.5.35, 5.6.0 - 5.6.28, 7.0.0 - 7.0.20, 7.1.0 - 7.1.33, 7.2.0 - 7.2.33, 7.3.0 - 7.3.33, 7.4.0 - 7.4.33, 8.0.0 - 8.0.30, 8.1.0 - 8.1.28, 8.2.0 - 8.2.18, 8.3.0 - 8.3.4, 8.3.6
array(3) { [0]=> int(0) [1]=> int(102) [2]=> int(203) }
Output for 8.3.5
Warning: PHP Startup: Unable to load dynamic library 'sodium.so' (tried: /usr/lib/php/8.3.5/modules/sodium.so (libsodium.so.23: cannot open shared object file: No such file or directory), /usr/lib/php/8.3.5/modules/sodium.so.so (/usr/lib/php/8.3.5/modules/sodium.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0 array(3) { [0]=> int(0) [1]=> int(102) [2]=> int(203) }

preferences:
203.29 ms | 402 KiB | 258 Q