Created
February 24, 2018 11:33
-
-
Save rainbow-alex/c577bdc119a0aaf74626bc0e9543adbe to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
abstract class ValueObject | |
{ | |
private $data = []; | |
final public function __construct() | |
{ | |
assert((function () { | |
foreach ((new ReflectionClass(static::class))->getProperties() as $p) { | |
$p = $p->getName(); | |
$this->data[$p] = $this->$p; | |
unset($this->$p); | |
} | |
})() || true); | |
} | |
final public function __get($p) | |
{ | |
if (!array_key_exists($p, $this->data)) { | |
$className = static::class; | |
throw new \Error("Instance of $className does not have a property named $p"); | |
} | |
return $this->data[$p]; | |
} | |
final public function __set($p, $v) | |
{ | |
if (!array_key_exists($p, $this->data)) { | |
$className = static::class; | |
throw new \Error("Instance of $className does not have a property named $p"); | |
} | |
ob_start(); | |
debug_zval_dump($this); | |
preg_match('~refcount\((\d+)\)~', ob_get_clean(), $matches); | |
$refCount = $matches[1] - 3; | |
if ($refCount > 1) { | |
$className = static::class; | |
throw new \Error("Can't mutate instance of $className, it has more than one reference. Did you assign it without cloning?"); | |
} | |
$this->data[$p] = $v; | |
} | |
} | |
class Something extends ValueObject | |
{ | |
public $foo; | |
} | |
$v = new Something(); | |
$v->foo = "A"; | |
$v2 = clone $v; | |
$v2->foo = "B"; | |
var_dump($v->foo); | |
var_dump($v2->foo); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment