Skip to content

Instantly share code, notes, and snippets.

@inxilpro
Created October 12, 2022 14:13
Show Gist options
  • Save inxilpro/014b093d08472fc70c422203d9c722f4 to your computer and use it in GitHub Desktop.
Save inxilpro/014b093d08472fc70c422203d9c722f4 to your computer and use it in GitHub Desktop.
<?php
$a = 'foo';
dump($a); // "foo"
snapshot($a);
$a = 'bar';
dump($a); // "bar"
restore($a);
dump($a); // "foo"
<?php
function snapshot(&$variable)
{
return Snapshots::instance()->snapshot($variable);
}
function restore(&$variable) {
return Snapshots::instance()->restore($variable);
}
<?php
use Illuminate\Support\Collection;
class Snapshots
{
protected static ?self $instance = null;
public static function instance(): self
{
return static::$instance ??= new self();
}
public function __construct(
public Collection $cache = new Collection()
) {
}
public function &snapshot(&$variable)
{
$snapshot = $variable;
$this->cache[] = function(&$restoring) use (&$variable, $snapshot) {
if ($this->match($variable, $restoring)) {
$variable = $snapshot;
return true;
}
return false;
};
return $variable;
}
public function &restore(&$variable)
{
$this->cache = $this->cache->reject(function($matcher) use (&$variable) {
return $matcher($variable);
});
return $variable;
}
protected function match(&$a, &$b): bool
{
if ($a !== $b) {
return false;
}
return match(true) {
is_object($a) => true,
is_scalar($a) && $this->areLinked($a, $b) => true,
is_array($a) && $this->areLinked($a, $b) => true,
default => false,
};
}
protected function areLinked(&$a, &$b): bool
{
$backup = $a;
try {
$a = new stdClass();
return $b === $a;
} finally {
$a = $backup;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment