XHTMLforum

XHTMLforum (http://xhtmlforum.de/index.php)
-   Serveradministration und serverseitige Scripte (http://xhtmlforum.de/forumdisplay.php?f=80)
-   -   PHP OOP: Datenbankeintrag Klasse - ein paar theoretische Überlegungen (http://xhtmlforum.de/showthread.php?t=57793)

braindead 21.07.2009 17:18

PHP OOP: Datenbankeintrag Klasse - ein paar theoretische Überlegungen
 
Hallo,
mein aktuelles Problem ist etwas theoretischer, es geht um die objektorientierte Implementierung eines Datenbanktabelleneintrages.

Also eine Klasse dehren Objekte Einträge in meiner Mysql Datenbank entsprechen sollen. Der Sinn des ganzen ist der, das ich diese Klasse später vererben will an eine Komentar bzw. Forumspostklasse (ein solcher Forumspost stellt ja auch einen Datenbankeintrag dar) und außerdem noch an eine ToDolisten-Eintragsklasse (mehrere Webmaster arbeiten an einer Seite, inhaltilich, und sollen sich gegenseitig über einen ToDo-Liste auf dem neusten Stand halten können, auch hier wird das ganze über die Mysql Datenbank gespeichert).

Zunächst, ich bin recht neu in der objektorientierten Programmierung und miss/überinterpretiere das Konzept der Klassen vieleicht ein wenig.

Um das mal zu demonstrieren: die db_tableentry Klassen (die Datenbanktabelleneinstragsklasse) bzw. ihre Objekte repräsentieren ja Datenbankeinträge, im Prinzip besizt sie Methode um Änderungen an diesem Eintrag (An sich selbst) vornehmen zu können, und zur Ausgabe. Aus diversen Gründen besitzt sie auch einen Satz Variablen für die Aufnahme der Spalteneintrage die diese Einstrag in der Tabelle besitzt. Und genau diese Redundanz (der Datenbeitrag "manifestiert" sich an zwei Orten 1. in der Datenbank selber und 2. durch die Belegung der Klassenvariablen die ebenfalls die Spalteneinträge enthalten) macht mir Probleme.

Es stellen sich mir nämlich die Fragen:
1. muss ich bei der erzeugung eines neues Objektes dieser Klasse, bzw. im Konstruktor der Klasse diese Doppelpräsens der Tabelleneintragsinformation (einmal in der Tabelle und dann noch in den Klassen/Objekt Variablen) besonders berücksichtigen? Immerhin darf es ja (oder darf es doch) auf keinen Fall passieren, das in der Datenbank selbst andere Informationen stehen als in den Klassenvariablen! Sonnst müsste ja noch geklärt werden welches die echten/korrekten Informationen sind. Das heist ich muss beim verändern der Information, die Information sowohl in den Variablen und in der Datenbank gleichzeitig ändern?

Was mich zur 2. Frage führt:
Dieses Objekt stellt ja einen (existierenden?) Datenbankeintrag dar. Sollte diese Klasse also nun auch Methoden zur Erzeugung eines neuen Eintrags besitzen? Ein Beispiel, ein Auto ist ein Objekt mit den Methoden: Gas geben, Lenken usw. aber es hat sicher keine Methode mit dem Namen "erzeuge ein neues Auto" oder "kaufe auto", ich hoffe ihr versteht mein Dilemma? Das Erzeugen eines Klassenobjektes (mit $objekt = new classname!, nicht das anlegen eines neues Eintrags) entspricht hier ja nicht einem "kaufe Auto" sondern eher einem "registriere die existens eines Autos".
Wie umgehe ich das Problem? Eine weitere Klasse oder eher eine globale Funktion zur Erzeugung eines Datenbankeintrages?

3. Außerdem soll die Klasse eine Statische Methode erhalten zur Erzeugung einer Liste/eines Arrays von Datenbankeinstragsobjekten und zwar aus Performance Gründen, in der Regel liefert ein Datenbank Select Query ja mehrere Eintrage und die will ich nicht einzeln per PHP als solche db_tableentry Objekte realisieren sondern ich will das mir die Statische Methode das Result gleich auf mehrere Objekte (in einem Array) aufteilt.
Meiner Ursprünglichen Idee nach, würde eine Erzeugung eines solchen Objektes, mit der Verarbeitung der Tabelleninformation und einer Eintragsid funktionieren, der Konstruktur holt dann per select Query den Eintrag mit der gegebenen ID aus der gegebenen Tabelle und speichert die Werte in seinen Variablen. Wenn ich das bei einer Liste einzeln machen würde, würde für jeden Listeneintrag ein neuer select Query abgesetzt werden, was ja nicht so gut ist. Deshalb soll diese Statische Methode die Objekte auch erzeugen können ohne das bei der Erzeugung ein query abgeschickt werden muss, also der Konstruktor soll ein Argument besitzen (vieleicht "trusted" genannt) das die Statische Methode mit dem Wert "true" übergibt plus einem assoziativen Array ([Spaltenmame]->Spaltenwert) mit dem das Objekt erzeugt wird.

Kann man das so machen?

Gumbo 21.07.2009 17:29

Wozu soll das alles gut sein? Welchen Vorteil hast du bei einer solchen „Datenbanktabelleneinstragsklasse“ gegenüber der klassischen Herangehensweise?

Ich denke, du machst es dir nur unnötig kompliziert. Das Prinzip der Objektorientierung kann auch übertrieben werden.

braindead 21.07.2009 17:35

Wie gesagt ich will die Klasse später vererben, um mir dann Programmierarbeit zu ersparen. Ich habe in diesem Projekt viele Stellen wo ich sowas wie Gästebucheintrage, Forumseinträge, diverse Komonikationskomentare etc behandeln muss, die sich alle durch leichte veränderungen voneinander Unterscheiden. So muss z.b. der Gästebuchseintrag keinem User zugeordnent werden, die ToDo Listeneinträge brauchen ein Atribut Status (ob das Problem schon abgehandelt wurde oder nicht) usw. da finde ich den Vererbungsansatz einer allgemeinen Klasse ganz praktisch ich kann dann ganz übersichtlichen Code schreiben:
todoobjekt->read() (zum anzeigen)
todoobjekt->done() (zum abhaken)
etc
Natürlich könnte ich hier auch mit Funktionen arbeiten, da ich hier aber viele ähnliche Objekte zu handhaben habe (wo schon aufgelistet) müsste ich da Teilweise Funktionen nur leicht umschreiben und dafür größe Teile des Codes kopieren. Vieleicht liege ich hier auch falsch, zumindest schein mir der Einsatz von Methoden die übersichtlichste Art des codings zu sein, in meinem Fall.

mantiz 21.07.2009 17:36

Hehe, das ist ein wenig, wie das Huhn-oder-Ei-Problem. :)

Ich hab' mich bis vor einigen Wochen genau dasselbe gefragt, weil ich auf meine "Objekte" in der Datenbank endlich objektorientiert zugreifen wollte.

Die Lösung lautet Registry (zumindest bei mir). :)

Am Beispiel Kommentar:
Du hast eine DB-Tabelle, wo die Kommentare drin stehen, also schreibst Du dir eine Klasse Kommentar, welche einem Kommentar entspricht.
Zusätzlich schreibst Du Dir eine KommentarRegistry über welche Du Kommentare auflisten, hinzufügen, ändern, löschen kannst.

Der Klasse Kommentar spendierst Du einen Konstruktor mit 2 Parametern, 1. Parameter ist eine Referenz auf die KommentarRegistry (falls man da mal was mit machen möchte), 2. Parameter ist ein assoziatives Array mit Feldname => Wert.

Jetzt ist das Beispiel mit den Kommentaren recht simpel, angenommen, Du hast Artikel, welche kommentiert werden können, dann hast Du eine ArtikelRegistry, über welche die Artikel geladen, geändert, usw. werden.
Die Artikel-Klasse selbst kann aber als Registry für die Kommentare fungieren, wodurch Du eine Objekt-Hierarchie erhälst.

Ich weiß zwar nicht, ob das die beste, oder zumindest eine gute Lösung ist, aber das ist mein derzeitiger Ansatz, evtl. hilft's Dir ja etwas weiter.

braindead 21.07.2009 17:44

Das ist interessant, mal überlegen ob ich damit klarkomme, bin wie gesagt noch nicht so bewandert auf dem Gebiet. Aber ich versuche das mal umzusetzen.

mantiz 21.07.2009 17:57

Wie gesagt, ich hab' mich sehr lange schwer damit getan.

Meine Lösung sieht jetzt (vereinfacht) so aus:

Es gibt Namespaces, Tabellen, Datensätze, wie gesagt, vereinfacht, tatsächlich gibt es mehr. :)

Ein Namespace darf nur weitere Namespaces, oder Tabellen enthalten, eine Tabelle nur Datensätze, ein Datensatz nix.

Die Klasse Namespace fungiert als Registry für Namespaces und Tabellen, die Klasse Tabelle fungiert als Registry für Datensätze.

Zu Beginn des Scriptes wird ein virtueller globaler Namespace erstellt, also eine Instanz der Klasse Namespace, welchen es aber eigentlich nicht gibt. Dieser globale Namespace dient nur als Einstiegspunkt, um weitere Namespace oder Tabellen zu laden. Über die Tabellen-Objekte werden dann die Datensätze geladen, z.B. ungefähr so:
PHP-Code:

$globalNamespace->getNamespace('Core')->getTable('Artikel')->listRecords(...); 

Direkten Zugriff auf die DB versuche ich zu vermeiden, weil jede Klasse, die "Registry-Charakter" hat ebenfalls einen Cache implementiert, so dass nicht immer alle Datensätze geladen werden müssen, fertig bin ich damit aber auch noch nicht. :)

braindead 21.07.2009 18:30

Oha, ganz schön harter Tobak :) aber durchaus logisch und nachvollziehbar. Ich weiß nur nicht ob es sich für mein kleines Projekt lohnt das so krass aufzuziehen, ich meine wenn Performance keine Rolle spielen würde, dann auf jedenfall, garkeine Frage oder bei einem richtig großen Projekt auch. Ich muss mal darüber nachdenken und es wirken lassen :) Eine alternative wäre vieleicht einfach statische Methoden zu benuzen um Objekte neu anzulegen, mal sehen.

mantiz 21.07.2009 19:02

*g, ich wollte damit auch nicht sagen, dass Du es so aufziehen musst oder solltest. :)

Ich wollte Dir nur ein Beispiel geben, was damit theoretisch denkbar wäre.
Bei mir bildet dieses Konstrukt den neuen Kern meines CMS-Entwurfs, daher muss es schon etwas mächtiger sein. :)

Bei Dir würde ja evtl. schon eine simple Registry-Klasse reichen. :)

Kannst ja mal schreiben, sobald Du eine Lösung für Dich gefunden hast, würde mich interessieren. :)

Timo 21.07.2009 23:21

Vieleicht ist ja schon PDO was für dich.

inta 22.07.2009 13:34

PDO würde ich sowieso empfehlen, aber das ist ja keine Datenbankabstraktion.

Bisher nutze ich auch nur PDO direkt, aber mantiz Überlegungen finde ich sehr interessant, vor allem bei umfangreichen Anwendungen kann sich das bezahlt machen.


Alle Zeitangaben in WEZ +2. Es ist jetzt 01:19 Uhr.

Powered by vBulletin® Version 3.8.11 (Deutsch)
Copyright ©2000 - 2020, vBulletin Solutions, Inc.

© Dirk H. 2003 - 2020