Skip to content

Instantly share code, notes, and snippets.

@rainbow-alex
Created February 24, 2018 11:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rainbow-alex/c577bdc119a0aaf74626bc0e9543adbe to your computer and use it in GitHub Desktop.
Save rainbow-alex/c577bdc119a0aaf74626bc0e9543adbe to your computer and use it in GitHub Desktop.
<?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