Hallo bobby,
dass eine Superklasse auf protected-Elemente einer Subklasse zugreifen kann, ist eine PHP Spezialität. Sozusagen eine automatische Erzeugung virtueller Methoden.
Nach mehreren geistigen Iterationen bin ich aber bei der Idee angekommen, dass das alles eigentlich nur unnötiger Boilerplate-Code ist. Weil:
- dein ORM muss das Modell kennen (für Mapping Properties <-> DB Columns)
- die Zugriffe auf die Entity-Properties erfolgen ohnehin über __call
Und dann fragt man sich: Warum überhaupt noch Entity-Klassen. Warum nicht…
class ORM {
// Typkatalog, kommt aus irgendeiner Config-Quelle. Typprüfung könnte man noch einbauen.
// Katalog könnte auch über Klassenmodell repräsentiert werden.
private static $types = [
"Person" => [
"table" => "PersTable",
"properties" => ["name" => "string", "plz" => "string", "ort" => "string"]
]
];
private $type;
private $properties;
private $values = [];
public function __construct($type) {
// Unbekannte Typen abweisen
if (!isset(ORM::$types[$type])) throw new Exception();
// Property-Definitionen für diesen Entity-Typ übernehmen. $this->properties könnte man
// auch weglassen, dann muss man nur in jedem get/set durch den den Katalog navigieren
$this->type = $type;
$this->properties = ORM::$types[$type]["properties"];
}
// Zentrales Handling für get und set mit Speicherung der Werte in einem Array.
public function __call($name, $args) {
$operation = substr($name,0,3);
if ($operation != "get" && $operation != "set")
throw new Exception("Aufruf von unbekannter Methode $name");
$prop = lcfirst(substr($name,3));
if (!isset($this->properties[$prop]))
throw new Exception("$operation auf unbekanntes Property $prop");
if ($operation == "get") {
if (!isset($this->values[$prop])) return null;
$value = $this->values[$prop];
// Add I18N here
return $value;
} else {
if (count($args) != 1) throw new Exception("Setter erwartet genau einen Parameter");
// I18N here?
$this->values[$prop] = $args[0];
}
}
}
// Subklasse nur nötig weil eine Zusatzmethode gebaut wurde
class Person extends ORM {
public function __construct() {
parent::__construct("Person");
}
public function getAdresse() {
return $this->getPlz() ." ". $this->getOrt();
}
}
$e = new ORM("Person"); // Pseudo-POPO Entitäten
$e = new Person(); // Konstruktion von erweiterten Entitäten MIT eigenen Methoden
$e->setName("Rolf");
$e->setPlz("12345");
$e->setOrt("Dingenskirchen");
$name = $e->getName();
echo "Name ist $name\n";
echo "Adresse ist {$e->getAdresse()}\n";
Damit brauchst Du grundsätzlich nur noch noch Entitätsobjekte vom Typ ORM. Nur wenn Du noch Zusatzmethoden implementieren willst, wie hier für getAdresse, erzeugst Du eine abgeleitete Klasse. Natürlich kannst Du - der Einheitlichkeit halber - auch für jede Entität eine Subklasse ableiten, die nur den Konstruktor enthält.
Rolf
--
sumpsi - posui - clusi
sumpsi - posui - clusi