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)

Bookmark setzen... These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Bloglines
  • MisterWong
  • MySpace
  • Reddit
  • SEOigg
  • Technorati
  • TwitThis
  • Y!GG
  • Google Bookmarks

Weiterführende Links: