Ich habe eine nackte Knochen ORM-Implementierung, bestehend aus Daten-Mapper, die laden und persist Entitäten. Jeder Mapper verwaltet intern eine Identitätszuordnung für alle Entitäten, die aus der Datenbank gelesen werden, so dass die gleiche Entität nur einmal in den Speicher geladen wird.
Ich implementiere derzeit Lazy Loading für verwandte Entitäten mit einer Proxy-Klasse, die die verwandten Daten nur lädt, wenn auf eine Eigenschaft der Entität zugegriffen wird. Mein Problem ist, dass die Proxy-Klasse nicht die Entität selbst ist und nur verwendet wird, wenn die Entität indirekt geladen wird (über eine Beziehung). Daher wird jede ===-Prüfung, die die tatsächliche Entität mit einem Proxy vergleicht, der die gleiche Entität lädt, false zurückgeben. Mein Ziel ist es, dass sowohl die Entitäten als auch der Client-Code nichts von den Proxy-Objekten wissen.
Die Proxy-Klasse sieht in etwa so aus:
class EntityProxy
{
protected $_entity;
protected $_loader;
public function __construct(EntityProxyLoader $loader)
{
$this->_loader = $loader;
}
protected function _load()
{
if (null === $this->_entity)
{
$this->_entity = $this->_loader->load();
unset($this->_loader);
}
}
public function __get($name)
{
$this->_load();
return $this->_entity->$name;
}
public function __set($name, $value)
{
$this->_load();
$this->_entity->$name = $value;
}
}
Und die Mapper sehen in etwa so aus:
class PersonEntityMapper
{
// Find by primary key
public function find($id)
{
if ($this->inIdentityMap($id)
{
return $this->loadFromIdentityMap($id);
}
$data = ...; // gets the data
$person = new Person($data);
// Proxy placeholder for a related entity. Assume the loader is
// supplied the information it needs in order to load the related
// entity.
$person->Address = new EntityProxy(new EntityProxyLoader(...));
$this->addToIdentityMap($id, $person);
return $person;
}
}
class AddressEntityMapper
{
// Find by primary key
public function find($id)
{
...
$address = new AddressEntity($data);
$address->Person = new EntityProxy(new EntityProxyLoader(...));
$this->addToIdentityMap($id, $address);
return $address;
}
}
Wenn ich einen "PersonEntity"-Datensatz lade, der eine verwandte "AddressEntity" hat, und dann denselben "AddressEntity"-Datensatz direkt über den "AddressEntityMapper" lade und die beiden Objekte vergleiche, sind sie nicht identisch (da eines ein Proxy ist, der delegiert). Gibt es eine Möglichkeit, den in PHP eingebauten Objektvergleich außer Kraft zu setzen? Gibt es Vorschläge für einen besseren Weg, dies zu handhaben, ohne proxybewussten Code in die Entitäten und/oder den Client-Code einzuführen?
Ich bin mir auch bewusst, dass es für mich von Vorteil wäre, ein bestehendes und etabliertes ORM zu übernehmen, aber es gibt verschiedene Probleme, die mich daran hindern, dies zu tun.