Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
1 Einleitung
2 Die Basis der Objektorientierung
3 Die Prinzipien des objektorientierten Entwurfs
4 Die Struktur objektorientierter Software
5 Vererbung und Polymorphie
6 Persistenz
7 Abläufe in einem objektorientierten System
8 Module und Architektur
9 Aspekte und Objektorientierung
10 Objektorientierung am Beispiel: Eine Web-Applikation mit PHP 5 und Ajax
A Verwendete Programmiersprachen
B Literaturverzeichnis
Stichwort
Ihre Meinung?

Spacer
 <<   zurück
Objektorientierte Programmierung von Bernhard Lahres, Gregor Rayman
Das umfassende Handbuch
Buch: Objektorientierte Programmierung

Objektorientierte Programmierung
2., aktualisierte und erweiterte Auflage, geb.
656 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1401-8
Pfeil 10 Objektorientierung am Beispiel: Eine Web-Applikation mit PHP 5 und Ajax
  Pfeil 10.1 OOP in PHP
    Pfeil 10.1.1 Klassen in PHP
    Pfeil 10.1.2 Dynamische Natur von PHP
  Pfeil 10.2 Das entwickelte Framework – Trennung der Anliegen – Model View Controller
    Pfeil 10.2.1 Trennung der Daten von der Darstellung
  Pfeil 10.3 Ein Dienst in PHP
    Pfeil 10.3.1 Datenmodell
    Pfeil 10.3.2 Dienste – Version 1
  Pfeil 10.4 Ein Klient in Ajax
    Pfeil 10.4.1 Bereitstellung der Daten
    Pfeil 10.4.2 Darstellung der Daten
  Pfeil 10.5 Ein Container für Dienste in PHP
    Pfeil 10.5.1 Dispatcher
    Pfeil 10.5.2 Fabrik
    Pfeil 10.5.3 Dependency Injection
    Pfeil 10.5.4 Sicherheit
  Pfeil 10.6 Ein Klient ohne JavaScript
  Pfeil 10.7 Was noch übrigbleibt


Rheinwerk Computing - Zum Seitenanfang

10.3 Ein Dienst in PHP  Zur nächsten ÜberschriftZur vorigen Überschrift

In diesem Abschnitt werden wir einen Dienst realisieren, der Zugriffe auf die Kontaktdaten eines Anwenders in einer Datenbank ermöglicht. Dazu werden wir in Abschnitt 10.3.1 zunächst das zugehörige Datenmodell entwickeln. In Abschnitt 10.3.2 setzen wir darauf aufbauend den Dienst für die Kontaktverwaltung und die entsprechenden Operationen um.


Rheinwerk Computing - Zum Seitenanfang

10.3.1 Datenmodell  Zur nächsten ÜberschriftZur vorigen Überschrift

Wir möchten, dass jeder Benutzer unserer Anwendung seine eigenen Kontakte verwalten kann und dass er zu jedem Kontakt beliebige Einträge speichern kann – seien es Namen, Telefonnummern, Geburts- und Jahrestage, Adressen oder auch andere benutzerdefinierte Eintragstypen.

In dem vorherigen Satz haben wir die Substantive kursiv gesetzt, von denen wir meinen, dass wir sie als Klassen in unserem Modell verwenden können.

Besprechen wir jetzt kurz, welche Attribute die jeweiligen Klassen haben sollten: Ein Benutzer muss einen Benutzernamen und ein Kennwort haben. Ein Kontakt ... nun, welche Einträge müssen wir bei einem Kontakt speichern? Sollten wir bei jedem Kontakt den Vor- und den Nachnamen speichern? Wie speichern wir dann aber den Namen der netten Pizzeria um die Ecke, bei der wir von Zeit zu Zeit anrufen? Ist »Primavera« der Vor- oder der Nachname? Überlassen wir diese Entscheidung lieber den Benutzern unserer Anwendung – lassen wir sie beliebige Eintragstypen definieren.

Der Benutzer soll bestimmen, welche Einträge ein Kontakt haben kann, welche mehrfach vorkommen können und welche für einen Kontakt eindeutig sein müssen.

Abbildung 10.1    Klassendiagramm mit den wichtigsten Klassen unserer Kontaktverwaltung

Diskussion: Modell der Kontaktverwaltung

Bernhard: Hör mal, das kann doch nicht das Modell unserer Anwendung sein. Hier sehe ich nur die Daten und keine Funktionalität. Was ist zum Beispiel mit dem Dienst, der die Sicherheit der Anwendung gewährleisten soll, von dem wir oben sprechen?

Gregor: Du hast vollkommen recht. Hier haben wir nur die Entitäten modelliert, mit denen unsere Anwendung arbeitet, um daraus ein Datenmodell entwickeln zu können. Wir wollen die Daten in einer relationalen Datenbank speichern, und dazu müssen wir die Tabellenstruktur definieren.Selbstverständlich werden wir später auch die anderen Bereiche der Anwendung modellieren.

Bernhard: Dann lass uns also jetzt das Datenmodell entwickeln.

Wenn wir die Regeln aus Kapitel 6, »Persistenz«, beachten, kommen wir zu dem einfachen Datenmodell, das in Abbildung 10.2 dargestellt wird. Obwohl in unserer Anwendung jeder Benutzer einen eindeutigen Benutzernamen hat und somit der Benutzername ein natürlicher Schlüssel der Relation Benutzer ist, werden wir einen Ersatzschlüssel als den Primärschlüssel dieser Relation verwenden.

Jeder gespeicherte Kontakt gehört nämlich einem Benutzer, und so muss jeder Datensatz der Tabelle Kontakt auf einen Datensatz in der Tabelle Benutzer verweisen – wir brauchen also einen Fremdschlüssel für die Tabelle Kontakt. Würden wir den Benutzernamen als den Primärschlüssel der Tabelle Benutzer verwenden, müssten wir ihn auch in der Tabelle Kontakt speichern. Dies wäre weniger effizient, als einen numerischen Ersatzschlüssel zu speichern, und eine mögliche Änderung des Benutzernamens zu implementieren wäre komplizierter.

Da wir für einen Kontakt überhaupt keine Attribute definiert haben, bleibt uns nichts Weiteres übrig, als für die Tabelle Kontakt ebenfalls einen Ersatzschlüssel zu definieren.

Bei den anderen Tabellen sind wir ähnlich vorgegangen, und das Ergebnis ist das Datenmodell [Ein SQL-Skript für das Erstellen der Datenbankstruktur in einer MySQL-Datenbank befindet sich auf der Webseite zum Buch (www.objektorientierte-programmierung.de). ] , das in Abbildung 10.2 dargestellt ist.

Abbildung 10.2    Datenmodell unserer Kontaktverwaltung

Der interessierte Leser kann gerne überprüfen, ob [Wir sollten hier statt »ob« lieber »dass« schreiben, nicht wahr? ] das Datenmodell normalisiert ist entsprechend der Regeln, die in Abschnitt 6.4, »Normalisierung und Denormalisierung«, beschrieben sind.

Diskussion: Relationen im Datenmodell

Bernhard: Um ehrlich zu sein, bin ich von diesem Datenmodell überhaupt nicht begeistert. Es ist zu allgemein. Wir haben gar nicht die wirkliche Datenstruktur der Kontakte analysiert. Dabei ist aber klar, dass die Benutzer meistens Namen, Telefonnummern, Adressen und E-Mail-Adressen ihrer Kontakte speichern werden. Ich verstehe schon, dass wir dem Benutzer die Freiheit geben sollten, eigene Eintragstypen zu definieren, aber auf diese Weise verlieren wir zum Beispiel die Möglichkeit, Indizes für bestimmte Einträge wie den Nachnamen anzulegen.Ich finde, mit etwas mehr Analyse und Design könnten wir ein viel besseres Datenmodell entwickeln.

Gregor: Das stimmt. Es ist selten eine gute Idee, in einer relationalen Datenbank die Relationen in einer Name-Wert-Tabelle zu speichern, wie wir es in der Tabelle Eintrag tun. Es ist meist besser, die Relationen ausführlicher zu analysieren und sie dann in »eigenen« Tabellen abzubilden. Dies würde aber dieses Kapitel in die Länge ziehen. Lassen wir hier dem Leser die Möglichkeit, unsere Beispielanwendung zu verbessern – zum Beispiel so, dass er das Datenmodell dahingehend verändert, dass Geburts- und Jahrestage in Spalten vom Typ DATE statt VARCHAR gespeichert werden. Und kehren wir zum Thema PHP zurück.

Bernhard: Na, dann aber los!
Rheinwerk Computing - Zum Seitenanfang

10.3.2 Dienste – Version 1  topZur vorigen Überschrift

Der erste Dienst, den wir implementieren, soll Operationen bereitstellen, die den Zugriff auf die Kontaktdaten eines angemeldeten Benutzers ermöglichen. Die erste Operation, die wir implementieren, wird die Kontaktdaten des Benutzers auflisten.

Wie wird sich der Benutzer aber anmelden? Und wie kommen die Kontaktdaten in die Datenbank? Gute Fragen! Bis wir entsprechende Dienste und Operationen implementieren, müssen wir einfach mit der Annahme leben, dass der Benutzer mit der Benutzer-Id 1 angemeldet ist und dass die entsprechenden Daten in der Datenbank existieren. [Auf der Webseite zum Buch (www.objektorientierte-programmierung.de) finden Sie ein SQL-Skript, mit dem Sie die Beispieldaten in die Datenbank einfügen können. ] Wir werden bald Dienste zur Benutzerverwaltung und zur Kontaktdatenpflege implementieren.

Unser erster Dienst würde also etwa so aussehen:

class Kontakte {
   public function auflisten() { 
      ...   } 
}

Die Funktion auflisten wird eine Liste der Kontakte zurückgeben.

Jeder Kontakt selbst wird als eine Liste von Objekten zurückgegeben, die die Eigenschaften des Kontaktes repräsentieren. Diese Objekte haben drei Attribute: id und name kommen aus der Tabelle Eintragstyp und das Attribut eintrag ist ein Array, das die Werte aus der Tabelle Eintrag enthält.

Nur wenn in der Tabelle Eintragstyp in der Spalte ett_eindeutig spezifiziert ist, dass der Wert eindeutig ist, wird in dem Attribut eintrag statt eines Arrays nur ein Wert zurückgegeben. Wir könnten zum Beispiel festlegen, dass es nur eine E-Mail-Adresse zu einem Kontakt geben kann, aber mehrere Telefonnummern.

Hier also unsere erste Version des Dienstes:

class Kontakte { 
    private static function db() {  
        $db = new mysqli('localhost', 'buch', 'buch', 'buch'); 
        $db->set_charset("utf8"); 
        return $db; 
    } 
 
    private function benutzerId() {  
        return 1; 
    } 
 
    public function auflisten($kontaktid = -1) {  
        $db = self::db(); 
        try { 
            $stmt = $db->prepare(" 
                SELECT k.knt_id, t.ett_id, t.ett_name, 
                       t.ett_eindeutig, e.etg_id, e.etg_wert 
                FROM kontakt k 
                INNER JOIN eintrag e ON k.knt_id = e.knt_id 
                INNER JOIN eintragstyp t ON t.ett_id = e.ett_id 
                WHERE k.bnz_id = ? 
                AND (k.knt_id = ? or ? = -1) 
                ORDER BY k.knt_id, t.ett_reihenfolge,  
                         t.ett_name, e.etg_id 
            "); 
 
            if (!$stmt)  
                throw new SQLException($db->error, $db->errno); 
            $benutzerid = $this->benutzerId(); 
            $stmt->bind_param("iii",  
                      $benutzerid, $kontaktid, $kontaktid); 
            $stmt->bind_result($kontaktid, $typid,  
                      $typname, $eindeutig, $wertid, $wert); 
            $stmt->execute(); 
 
            $daten = array(); 
            $letzterKontakt = -1; 
            $letzterTypid = null; 
            while ($stmt->fetch()) { 
                if ($kontaktid != $letzterKontakt) { 
                    $letzterKontakt = $kontaktid; 
                    $eintrag = -1; 
                } 
                if ($letzterTypid != $typid) { 
                    ++$eintrag; 
                    $daten[$kontaktid][$eintrag]->name = 
                         $letzterTypname = $typname; 
                    $daten[$kontaktid][$eintrag]->id = 
                         $letzterTypid = $typid; 
                } 
                if ($eindeutig) { 
                    $daten[$kontaktid][$eintrag]->eintrag = 
                        Array('id' => $wertid, 'wert' => $wert); 
                } else { 
                    $daten[$kontaktid][$eintrag]->eintrag[] = 
                       Array('id' => $wertid, 'wert' => $wert); 
                } 
            } 
            $stmt->close(); 
            $db->close(); 
            $ergebnis = Array( "daten" => $daten ); 
            return $ergebnis; 
        } catch (Exception $e) { 
            if ($stmt) $stmt->close(); 
            if ($db) $db->close(); 
            throw $e; 
        } 
 
    } 
}

Listing 10.3    Der Dienst »kontakte.php«

Ab Zeile haben wir eine einfache Methode implementiert, die eine MySQL-Datenbankverbindung erstellt. Wir gehen in diesem Beispiel davon aus, dass der Datenbankserver auf demselben Server wie unser Webserver installiert ist und dass der Datenbankname, der Datenbankbenutzername und dessen Kennwort alle buch lauten. Diese Einstellungen sollten wir lieber in eine Konfigurationsdatei auslagern.

Ab Zeile »implementieren« wir die Methode, die uns die Id des aktuell angemeldeten Benutzers zurückgibt – zurzeit kennt unsere Anwendung nur einen einzigen Benutzer, der sich gar nicht anzumelden braucht.

Schließlich implementieren wir ab Zeile die Methode auflisten, die uns entweder alle Kontakte des Benutzers (wenn das Argument $kontaktid nicht angegeben wird oder den Wert –1 hat) oder einen spezifizierten Kontakt zurückgibt.

So, jetzt haben wir unseren ersten Dienst implementiert, mit dem die Daten aus der Datenbank gelesen werden können. Doch wie übermitteln wir die Daten an die Darstellungslogik?

Im folgenden Abschnitt 10.4, »Ein Klient in Ajax«, werden wir zeigen, wie die Darstellungslogik unter Verwendung von JavaScript und Ajax umgesetzt werden kann. In Abschnitt 10.5, »Ein Container für Dienste in PHP«, realisieren wir dann den Rahmen für die Verwendung von weiteren Diensten in unserer Anwendung. Schließlich zeigen wir in Abschnitt 10.6, »Ein Klient ohne JavaScript«, wie sich die Darstellungslogik einfach anpassen lässt, so dass die resultierenden Seiten rein HTML-basiert sind.



Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

 <<   zurück
  Zum Rheinwerk-Shop
Neuauflage: Objektorientierte Programmierung






Neuauflage:
Objektorientierte Programmierung

Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Java ist auch eine Insel






 Java ist auch
 eine Insel


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: C++ Handbuch






 C++ Handbuch


Zum Rheinwerk-Shop: Einstieg in Python






 Einstieg in Python


Zum Rheinwerk-Shop: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern