PHP – Klassen in Klassen – Class Nesting

PHP Kurs - Der Einstieg Wiederverwendbarer Code ist ein wichtiges Schlagwort für die
Objektorientierte Programmierung, doch wie kann man vorgehen, wenn
man mit Vererbung nicht weiter kommt?

Was bringt "class nesting" ?

Jeder Programmierer weiß, das es weder Sinn noch Spass macht,
elementare Funktionen jedesmal neu zu schreiben. Wichtige Stichworte
sind dabei die Modularität und wiederverwendbarer
Code
, um Zeitverluste bei Erstellung sowie Änderung von
Applikationen zu vermeiden und potentielle Fehlerquellen auszuschliessen.

Eine Guestbook – Klasse

Eine Guestbook Klasse sollte folgende Methoden beinhalten:

a) Einträge in eine Datenbank schreiben
b) Vorhandene Einträge darstellen
c) Neue Einträge per mail an den owner schicken
d) Ungewollte Einträge wieder löschen
e) Zur Darstellung Templates benutzen, die in Dateien bereit liegen
f) …

Mit der Vererbung über extends kommt man bei einem solchen
Problem nicht wirklich weiter, da 2-3 Klassen ( Datenbank,Mail,File)
benutzt werden sollen, die keine Beziehung untereinander
haben.

Man muss dennoch über die Guestbook-Klasse auf die Methoden
der anderen Klassen zurückgreifen. Dieses Problem kann man
lösen, indem man in der Guestbook-Klasse Instanzen der anderen
Klassen erzeugt, und so auf die einzelnen Methoden der verschiedenen
Klassen zugreifen kann.

Zunächst die Datenbank-Klasse, welche die Verbindung, das Senden
von Querys, und die Auswahl der Datenbank steuert. Zunächst
sollte jedoch über folgendes
SQL – Statement die Tabelle "guest" angelegt werden.

SQL – Statement


create table guest (
NUMMER int not null auto_increment,
DATUM date,
NAME varchar(255),
EMAIL varchar(255),
HEADING varchar(255),
MESSAGE text,
key(NUMMER)
);

Das Feld "nummer" ist der eindeutige Bezeichner eines
Datensatzes, der Primary Key, über diesen wird auf die einzelnen
Werte des Datensatzes zugegriffen. Ein Datensatz entspricht einem
Eintrag im Gästebuch.

Die Datenbank – Klasse
Wichtig für den weiteren Verlauf ist, das die Klasse genauso
heißt, wie die Datei.

<?php
// Dateiname: db_klasse.php

class db_klasse
{
var $host = "localhost";
var $user = "ich";
var $pass = "meinpass";
var $dbname = "meinedb";
var $db_link = false;

function db_klasse() //Konstruktor ruf db_connect() auf
{
$this->db_connect($this->host,$this->user,$this->pass,$this->dbname);
}

function db_connect($host,$user,$pass,$dbname) //baut die verbindung
auf
{
$this->db_link = @mysql_pconnect($host,$user,$pass) or die ("Datenbankverbindung
nicht möglich!");
$this->db_choose($dbname);
}

function db_choose($dbname) // wählt die datenbank
{
@mysql_select_db($dbname) or die ("Datenbank konnte nicht ausgewählt
werden!");
}

function db_query($query) // sendet einen query
{
$res = @mysql_query($query, $this->db_link) or die ("Abfrage
war ungültig!".mysql_error());
return $res;
}
}
?>

In den ersten Zeilen werden die verwendeten Variablen, bzw. Eigenschaften
definiert, in diesen werden die Daten für die Verbindung gespeichert.
Die Klasse ist recht einfach aufgebaut, mit den drei elementaren
Datenbankmethoden.

Die Guestbook – Klasse muss gebrauch von diesen Datenbankfunktionen
machen, also muss innerhalb der Guestbook – Klasse ein Objekt der
Datenbank – Klasse instanziert werden. Diese Instanz der Datenbank
– Klasse wird in $class_obj gespeichert.


<?php
// Dateiname: guestbook.php

class guestbook
{
var $class_obj;

function guestbook($class_needed,$file_ending) // Konstruktor
{
// Die Klasse wird eingebunden
include($class_needed.$file_ending);
// Es wird eine Instanz der Klasse erzeugt, und "class_obj"
zugewiesen
$this->class_obj = new $class_needed;
}

function insert_entry($name,$email,$heading,$message) //Speichern
{
$datum = date("Ymd");
// Nun greifen wir auf die Funktionen der "db_klasse"-Instanz
zu
$this->class_obj->db_query("insert into guest ( DATUM,NAME,EMAIL,HEADING,MESSAGE)
values
(‘$datum’,’$name’,’$email’,’$heading’,’$message’)");
}

function show_all() //alle daten anzeigen
{
// Wiederum wird die "db-klasse" benutzt
$res = $this->class_obj->db_query("select * from guest
order by NUMMER desc");
while ( $row = mysql_fetch_array($res) )
{
echo "
Eintrag Nummer $row[0]:<br>
Datum: $row[1]<br>
Name: <a href=\"mailto:".$row[3]."\">$row[2]</a><br><br>
$row[4]<br>
$row[5]<br><br><br>
";
}
}
}
?>

Der Konstruktor guestbook() ist hierbei sehr interessant.
Dieser Konstruktor ist die erste Funktion, welche ausgeführt
wird. Die benötigte Klasse, und die Dateiendung dieser Klassendatei
wird an den Konstruktor übermittelt. Daraufhin wird die entsprechende
Datei eingefügt.
Daraufhin wird eine Instanz der eingefügten Klasse erzeugt.
Wichtig hierbei ist, das die Datei genauso heißt, wie auch
die Klasse, da über diesen Namen eine neue Instanz der Klasse
erzeugt wird. Diese wird dann $class_obj zugewiesen. Über
dieses Objekt kann nun auf die einzelnen Methoden der jeweiligen
Klassen zugegriffen werden.

Ein Testskript test.php

<?php
include("guestbook.php"); // Guestbook – Klasse
$TEST = new guestbook("db_klasse",".php");
$TEST->insert_entry("Olaf Waltersdorf","olaf@waltersdorf.net","Dies
ist ein Gästebucheintrag…","…aber kein besonders
guter!"); // neuer Eintrag
$TEST->show_all(); // Anzeige aller Einträge
?>

Interessanter Nebeneffekt

Doch die Möglichkeiten sind noch nicht voll ausgeschöpft.
Möchte man nachdem die Guestbook – Klasse abgearbeitet ist,
noch auf die Datenbank – Klasse zugreifen, kann von der ersten Instanz
"$class_obj" eine Kopie gemacht werden, und man
kann so über diese Kopie "$DB" erneut auf
die Datenbank – Klasse zugreifen. So können wir Variablen bzw.
Eigenschaften des Objektes $DB separat von $class_obj
während eines Durchlaufes des Skriptes ändern. In diesem
Beispiel wird die Eigenschaft, bzw. die Variable $user welche
den Usernamen des Datenbanklogins beinhält, in der kopierten
Instanz $DB verändert. Das Objekt $class_obj
bleibt von diesen Änderungen unbetroffen.

Erzeugung der Kopie

<?php
include("guestbook.php");
$GUEST = new guestbook("db_klasse",".php");

// Noch ist $GUEST->user = ich
$GUEST->class_obj->user = "Guestbook_Instanz_User";

// Wir erzeugen eine KOPIE der Instanz, und zwar im zum Zeitpunkt
der Zuweisung aktuellen! Zustand
$DB = $GUEST->class_obj;
echo $DB->user."<br>";

// Nun ändern wir den user in der Instanz-Kopie
$DB->user = "User_geaendert_von_Instanz_Kopie";
echo $DB->user."<br>";

// Wie man sieht hat die Kopie keinen Einfluss mehr auf die
ursprüngliche Instanz
echo $GUEST->class_obj->user;
?>

Der Nuten dieser zwei Objekte mag vielleicht ein wenig verwirrend
sein, doch liegt er Klar auf der Hand. Über das zweite Objekt
$DB können während eines Durchlaufes der
Guestbook – Klasse weitere Daten in der Datenbank gespeichert werden.
Das sind z.B. die IP des Benutzers, die Refferer Seite usw.
Über
$DB -> db_connect("localhost", "anderer_user","passwort","andere_db");
kann direkt beim Durchlauf des Skriptes eine Verbindung zu einer
anderen Datenbank geöffnet werden, in welcher man dann andere
Daten über die Methoden der Datenbank – Klasse speichern kann.

Die Instanz-Referenz
Durch Referenzierung kann man beim Verändern eines Wertes
z.B. einer Kopierten Instanz festlegen, dass auch der Wert in dem
Objekt verändert wird, von welchem man eine Kopie erzeugt hat.

$DB = & $GUEST->class_obj;

Die Referenz wird durch das vorangestellte & erzeugt. Alle
Änderungen in den Eigenschaften von $DB werden
nun auch in dem Objekt $class_obj gemacht.

Um den Artikel komplett zu verstehen benötigt man einiges Basiswissen
zu OOP mit PHP. Wer diese Technik des "Nestings"
jedoch gut beherrscht, kann verschiedene Klassen und Methoden beliebig
tief ineinander verschachteln, und über die einzelnen Instanzen
auf jede einzelne Funktion zurückgreifen.
So kann man viele Klassen in einer Klasse zentrieren, und somit
auf die vielen Methoden zurückgreifen.

Schlusswort des Autors

Dieser Artikel ist der deutschen PHP-Community gewidmet, ohne
die ich ihn nicht hätte schreiben können. Es ist an der
Zeit, etwas zurückzugeben…hoffentlich hilft es dem ein oder
anderen!

Alle Beispielskripte stehen zum freien Download bereit.

Vielen dank an Olaf
Waltersdorf
, der uns diesen Artikel zur Verfügung gestellt
hat.

(owd)

This entry was posted in PHP. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *