Last active
February 15, 2016 19:28
-
-
Save ralphschindler/86ea9b8df11c0093db66 to your computer and use it in GitHub Desktop.
The "No-framework ORM tool for generating proxies capable of strategically mapping data into clean POPO entities without bleeding concerns or doesn't require a tool to write generated code to disk in under 100 lines of code" prototype. </runon-and-exhale>
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 | |
namespace EntityMapperFramework { | |
class EntityMapper { | |
public function __construct() { | |
stream_wrapper_register('dynamicproxygenerator', __NAMESPACE__ . '\DynamicProxyGeneratorStream'); | |
} | |
public function createProxy($entity) { | |
$class = get_class($entity); | |
$proxyClass = $class . 'Proxy'; | |
include_once "dynamicproxygenerator://$class?strategy=ProxyProtectedPropertyMapperStrategy"; | |
return (new $proxyClass)->setEntity($entity); | |
} | |
} | |
class DynamicProxyGeneratorStream { | |
protected $position; | |
protected $currentCode; | |
public function stream_open($path, $mode, $options, &$opened_path) { | |
$parsed = parse_url($path); | |
$fqClassName = $parsed['host']; | |
parse_str($parsed['query'], $queryParts); | |
$strategy = $queryParts['strategy']; // strategy could be picked at runtime, or by configuration | |
$ref = new \ReflectionClass($fqClassName); | |
$namespace = $ref->getNamespaceName(); | |
$className = $ref->getShortName(); | |
$this->currentCode = "<?php namespace {$namespace} { " | |
. "class {$className}Proxy extends \\{$fqClassName} {" | |
. "use \EntityMapperFramework\ProxyEntityTrait;" | |
. "use \EntityMapperFramework\\{$strategy}Trait; } }"; | |
$this->position = 0; | |
return true; | |
} | |
public function stream_read($count) { | |
$ret = substr($this->currentCode, $this->position, $count); | |
$this->position += strlen($ret); | |
return $ret; | |
} | |
public function stream_eof() { | |
return $this->position >= strlen($this->currentCode); | |
} | |
public function stream_stat() { | |
$t = time(); | |
return array(0, 0, 0, 0, 0, 0, 0, strlen($this->currentCode), $t, $t, $t, -1, -1); | |
} | |
} | |
trait ProxyEntityTrait { | |
protected $entity; | |
public function setEntity($entity) { | |
$this->entity = $entity; | |
return $this; | |
} | |
} | |
trait ProxyProtectedPropertyMapperStrategyTrait { | |
public function map($mapping, $data) { | |
foreach ($data as $n => $v) { | |
$this->entity->{$mapping[$n]} = $v; | |
} | |
return $this; | |
} | |
} | |
} | |
// Represents the model part of the application | |
namespace MyApplication\Model { | |
class FooEntity /* a POPO Entity, should have no knowledge of persistence layer */ { | |
protected $aNumber; | |
protected $bString; | |
public function getANumber() { return $this->aNumber; } | |
public function getBString() { return $this->bString; } | |
} | |
class MySimpleOrmFooRepository /* implements FooRepository */ { | |
protected $fooMap = ['a_number' => 'aNumber', 'b_string' => 'bString']; | |
protected $proxies = []; | |
public function __construct() { | |
$this->entityMapper = new \EntityMapperFramework\EntityMapper; // should be injected service | |
} | |
public function getFoo() { | |
$foo = new FooEntity; | |
$proxy = $this->entityMapper->createProxy($foo); | |
$this->proxies[spl_object_hash($proxy)] = $proxy; // for future use, like calling Repo::save() | |
$proxy->map($this->fooMap, ['a_number' => 15, 'b_string' => 'The B Team']); | |
return $foo; | |
} | |
} | |
} | |
// Represents the code that calls into the model, like a controller or other service | |
namespace { | |
$repo = new MyApplication\Model\MySimpleOrmFooRepository; | |
$foo = $repo->getFoo(); | |
assert($foo->getANumber() == 15); | |
assert($foo->getBString() == 'The B Team'); | |
echo "Assertions passed\n"; var_dump($foo); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment