Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 Beispiel Aufgabe: ist_vater_von id todessdatum <0,n> geburtsdatum <0,1> Person • Ableitung Datenbankschemata • Erstellung OR-Schicht • Erstellung von Methoden der Applikationslogik geschlecht <0,1> nachname ist_mutter_von Andreas Schmidt <0,n> vorname PHP (Teil 3) 1/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 Beispiel PDO_Util::connect("oci:dbname=oracledbwi", $account, $pw); $martin = CRUD_Person::get(4); $vater = $martin->getVater(); echo "Der Vater von $martin ist $vater\n"; print "Die Kinder von $vater sind:\n"; foreach ($vater->getKinder() as $kind) print " $kind\n"; $armes_weisenkind = CRUD_Person::get(8); $armes_weisenkind->setVater($martin); Andreas Schmidt PHP (Teil 3) 2/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 Tabellenstruktur create table person ( id number(8) primary key, vorname varchar2(60) not null, nachname varchar2(60) not null, geburtsdatum date not null, todesdatum date, vater_fk number(8) references person(id) on delete set null, mutter_fk number(8) references person(id) on delete set null, geschlecht char(1) check (geschlecht in ('M','W')) ); ID VORNAME NACHNAME G VATER_FK MUTTER_FK ---------- -------------------- -------------------- - ---------- ---------1 Peter Schulz M 2 Heide Langbain W 3 Monika Krieger W 4 Martin Schulz M 1 2 6 Andrea Huber W 5 Christoph Schulz M 4 6 7 Thomas Schulz M 1 2 8 Silke Meier W 9 Anna Schmidt W 10 Sandra Schmidt W 7 Andreas Schmidt PHP (Teil 3) 3/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 Class CRUD_Person (structure + constructor) class CRUD_Person { protected $id; protected $vorname; protected $nachname; protected $geburtsdatum; protected $todessdatum; protected $vater_fk; protected $mutter_fk; protected $geschlecht; function __construct($id, $vorname, $nachname, $geburtsdatum, $todesdatum, $vater_fk, $mutter_fk, $geschlecht) { $this->id = $id; $this->nachname = $nachname; $this->vorname = $vorname; $this->geburtsdatum = $geburtsdatum; $this->todesdatum = $todesdatum; $this->vater_fk = $vater_fk; $this->mutter_fk = $mutter_fk; $this->geschlecht = $geschlecht; } Andreas Schmidt PHP (Teil 3) 4/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 CRUD_Person - static method get($id) static function get($id) { $db = PDO_Util::get_connection(); $sql = "select * from person where id=?"; $stmt = $db->prepare( $sql ); $stmt->execute(array($id)); if ($row = $stmt->fetch()) return new CRUD_Person($row[0], $row[1], $row[2], $row[3], $row[4], $row[5], $row[6], $row[7]); else die("keine Person mit ID $id gefunden"); } Andreas Schmidt PHP (Teil 3) 5/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 CRUD_Person - instance method getVater() function getVater() { if (! $this->vater_fk) return null; $db = PDO_Util::get_connection(); $sql = "SELECT * FROM Person WHERE id=?"; $stmt = $db->prepare( $sql ); $stmt->execute(array($this->vater_fk)); if ($row = $stmt->fetch()) return new CRUD_Person($row[0], $row[1], $row[2], $row[3], $row[4], $row[5], $row[6], $row[7]); else die("Vater (ID: $this->vater_fk) von '$this' konnte nicht ermittelt werden"); } Andreas Schmidt PHP (Teil 3) 6/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 CRUD_Person - instance method setVater() function setVater($papa) { // Wichtig: vater_fk sowohl in der Instanz, als auch in der DB ändern !! // $db = PDO_Util::get_connection(); $this->vater_fk = $papa->id; $sql = "update Person set vater_fk=? where id=?"; $stmt = $db->prepare( $sql ); $stmt->execute(array($this->vater_fk, $this->id)); $affected_rows = $stmt->rowCount(); if ($affected_rows!=1) die("update hat nicht geklappt"); } Andreas Schmidt PHP (Teil 3) 7/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 CRUD_Person - instance method getKinder() function getKinder() { $db = PDO_Util::get_connection(); $sql = "SELECT * FROM Person WHERE vater_fk=? or mutter_fk=?"; $stmt = $db->prepare( $sql ); $stmt->execute(array($this->id, $this->id)); $list = array(); while ($row = $stmt->fetch()) $list[] = new CRUD_Person($row[0], $row[1], $row[2], $row[3], $row[4], $row[5], $row[6], $row[7]); return $list; } Andreas Schmidt PHP (Teil 3) 8/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 Applikationslogik - Klasse Person include_once 'OR-Stammbaum.php'; class Person extends CRUD_Person { function addKind($plage) { if ($this->geschlecht=='W') $plage->setMutter($this); else if ($this->geschlecht=='M') $plage->setVater($this); else die("Geschlecht von $this unspezifiziert ('$this->geschlecht'). Kann nicht zwischen Vater/Mutter unterschieden"); } Andreas Schmidt PHP (Teil 3) 9/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 Applikationslogik - Klasse Person function getEnkel() { $enkel = array(); $kinder = $this->getKinder(); foreach ($kinder as $kind) foreach ($kind->getKinder() as $e) $enkel[] = $e; return $enkel; } function getGeschwister() { die("bitte selbst implementieren"); } Hinweis: In OR-Schicht statt Instanzen der Klasse CRUD_Person Instanzen der Klasse Person erzeugen !! Andreas Schmidt PHP (Teil 3) 10/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 function getBrueder() { $vater = $this->getVater(); $mutter = $this->getMutter(); $brueder=array(); if ($vater) foreach ($vater->getKinder() as $kind) if ($kind->id != $this->id and $kind->geschlecht=='M') $brueder[$kind->id] = $kind; if ($mutter) foreach ($mutter->getKinder() as $kind) if ($kind->id != $this->id and $kind->geschlecht=='M' and ! array_key_exists($kind->id, $brueder)) $brueder[$kind->id] = $kind; return array_values($brueder); } Andreas Schmidt PHP (Teil 3) 11/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 ... mit PDO_Util Library function getKinder() { // selbe Methode wie auf Folie 8 $sql = "SELECT * FROM Person WHERE vater_fk=? or mutter_fk=?"; $list = PDO_Util::query($sql,array($this->id, $this->id)); $result = array(); foreach ($list as $row) $result[] = new Person($row['id'], $row['vorname'], $row['nachname'], $row['geburtsdatum'], $row['todesdatum'], $row['vater_fk'], $row['mutter_fk'], $row['geschlecht']); return $result; } // PDO_Util::query($sql, $paras) liefert als Ergebnis ein Array von // Dictionary Elementen // Test: print_r($list); Andreas Schmidt PHP (Teil 3) 12/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 // Wenn ein Konstruktor mit Dictionary als Parameter vorliegt: function __construct($dic) { $this->id = $dic['id']; $this->nachname = $dic['nachname']; ... } function getKinder() { $sql = "SELECT * FROM Person WHERE vater_fk=? or mutter_fk=?"; $list = PDO_Util::query($sql,array($this->id, $this->id)); $result = array(); foreach ($list as $row) $result[] = new Person($row); return $result; } Andreas Schmidt PHP (Teil 3) 13/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 ... mittels object_query(...) function getKinder() { $sql = "SELECT * FROM Person WHERE vater_fk=? or mutter_fk=?"; return PDO_Util::object_query($sql, 'Person', array($this->id, $this->id)); } // PDO_Util::object_query($sql, $class, $paras) nimmt als zusätzlichen Parameter // den Namen der Klasse von der Instanzen erzeugt werden sollen Wie funktioniert denn das im Detail ? Andreas Schmidt edit PDO_Util.php PHP (Teil 3) 14/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 Implementierung eines First Level Caches class Cache { private static $firstLcache = array(); static function isIn($class, $id) { // Test ob Instanz der Klasse $class mit $id im cache return array_key_exists("$class:$id", self::$firstLcache); } static function getInstance($class, $id) { // Auslesen der Instanz aus cache (oder null) if (self::isIn($class, $id)) { return self::$firstLcache["$class:$id"]; } else { return null; } } static function writeIntoCache($instance) { // Eintragen der Instanz in cache //(und zurückliefern) $key = get_class($instance).":".$instance->getId(); self::$firstLcache[$key] = $instance; return $instance; } Andreas Schmidt PHP (Teil 3) 15/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 Einsatz ... function getKinder() { $db = PDO_Util::get_connection(); $sql = "SELECT * FROM Person WHERE vater_fk=? or mutter_fk=?"; $stmt = $db->prepare( $sql ); $ok = $stmt->execute(array($this->id, $this->id)); $list = array(); while ($row = $stmt->fetch()) { $instance = Cache::getInstance('Person', $row[0]); if (! $instance) $instance = Cache::writeIntoCache(new Person($row[0], $row[1], $row[2], $row[3], $row[4], $row[5], $row[6], $row[7])); $list[] = $instance; } return $list; } Andreas Schmidt PHP (Teil 3) 16/17 Fakultät für Informatik & Wirtschaftsinformatik DB & IS II - WS 2016 Einsatz ... function getVater() { $instance = Cache::getInstance('Person', $this->vater_fk); if (! $instance) { $db = MDB2_Util::get_connection(); $sql = "SELECT id, vorname, nachname, geburtsdatum, todesdatum, vater_fk, mutter_fk, geschlecht FROM Person WHERE id=?"; // prepare, execute, fetchrow... // if (! $row) return null; $instance = Cache::writeIntoCache(new Person($row[0], $row[1], $row[2], $row[3], $row[4], $row[5], $row[6], $row[7])); } return $instance; } Andreas Schmidt PHP (Teil 3) 17/17