MVC - getter setter
Getter
- programmiertechnik
Hallo,
ich beschäftige mich gerade etwas mit dem MVC-Pattern. Jede Datenbanktabelle zum Beispiel entspricht einem Objekt/Klasse, sehe ich das richtig? Das Objekt "product" ist in einer Tabelle "products" abgebildet.
Dieses Ojbekt hat also getter und setter-methoden.
class product{
public String getName(){
return this.name;
}
public String setName(String n){
this.name = n;
}
}
Dumme Frage: via getName() erhalte ich den aktuellen Wert der Variablen name. Was ist aber, wenn ich den aktuelle Wert von name haben möchte, der schon in der DB-Tabelle steht? Müsste man dafür dann eine Methode getNameFromDB() oder sowas anlegen?
public String getNameFromDB(){
return this.someSQLMethodToGetNameFromDB();
}
Oder gibt es da elegantere Wege?
hi,
Ich würde hier eher eine reload_data funktion verwenden. die alles neu läd was zu dem datensatz gehört. Dabei gehe ich aber davon aus, dass alles überschrieben werden darf. Wenn du nur den original datensatz möchtest. solltest du eventuell noch irgendwas wie getOrgName einfügen und dafür einfach beim ersten laden dies speichern.
Das kommt auf deine wünsche an. Einzelne Daten neu laden ist spätestens wenn du noch den Geburtstag oder statt dem namen auch noch den vornamen willst, sehr wichtig, da es sonnst ja 2 DB abfragen braucht, die auch mit einer möglich gewesen wäre.
Kommt einfach auf deine Anforderung an.
Gruß Niklas
Tach!
ich beschäftige mich gerade etwas mit dem MVC-Pattern. Jede Datenbanktabelle zum Beispiel entspricht einem Objekt/Klasse, sehe ich das richtig?
Das hat mit dem MVC-Pattern nichts zu tun. Dir geht es eher um einen ORM oder etwas anderes zum Datenbank-Abstrahieren.
Und nun kommt es auf die Philosophie des ORM/whatever an, ob eine Tabelle gleich einer Klasse entspricht oder vielleicht nur die Struktur auf eine Klasse abgebildet wird. Eine ganze Tabelle (oder eine Teilmenge daraus), also Inhalt in strukturierter Form, wird wohl eher ein Array von Objekten sein.
Es kann aber auch sein, dass nicht die Tabellen 1:1 abgebildet sind, sondern aus den Ergebnisse von Abfragen - die ja durchaus weniger oder mehr Spalten als eine Tabelle enthalten können - ein Array mit ebendiesen Ergebnismengen-Objekten erstellt wird.
Dieses Ojbekt hat also getter und setter-methoden.
Kann man machen, muss man aber nicht. Besonders wenn außer dem reinen Lesen und Schreiben nichts weiter gemacht wird, ist das nur unnötiger Overhead beim Funktionsaufrufen.
Dumme Frage: via getName() erhalte ich den aktuellen Wert der Variablen name. Was ist aber, wenn ich den aktuelle Wert von name haben möchte, der schon in der DB-Tabelle steht? Müsste man dafür dann eine Methode getNameFromDB() oder sowas anlegen?
Du musst ein Objekt dieser Klasse erstellen. Das sollte mit dem gewünschten Inhalt aus der Datenbank gefüllt sein. Und dazu braucht es eine Abfrage mit Einschränkung auf einen bestimmten Datensatz (oder mehrere, wie auch immer die konkrete Aufgabenstellung ist).
Oder gibt es da elegantere Wege?
Für welche Aufgabenstellung? Ein ORM kann helfen, kann aber auch unnötiger Ballast sein. Möglich ist auch, dass du deine Abfragen selbst und gezielt auf deine Anforderung hin schreibst - mit den notwendigen Platzhaltern - und dir nur die Ergebnisse in ebenfalls genau passende Objekte fetchst.
dedlfix.
hi,
Du beschreibst ein ORM.
Dumme Frage: via getName() erhalte ich den aktuellen Wert der Variablen name. Was ist aber, wenn ich den aktuelle Wert von name haben möchte, der schon in der DB-Tabelle steht? Müsste man dafür dann eine Methode getNameFromDB() oder sowas anlegen?
[..]
Oder gibt es da elegantere Wege?
Ja, abhängig von der Programmiersprache. In Perl gibts es dazu tie(), das bindet eine Variable (scalar, array, hash) an eine Klasse. Getter, Setter werden nicht mehr explizit aufgerufen, sondern laufen im Hintergrund ab: In dem Moment, wenn der Variablen z.B. ein Wert zugewiesen wird, läuft im Hintergrund der Datenbankzugriff (Insert/Update).
In Perl sieht das dann z.B. so aus:
$object = tie %hash, 'ORM';
$hash{'object_id'}{'size'} = 123; # Method STORE wird aufgerufen, INSERT/UPDATE
$object->commit(); # expliziter Aufruf einer Methode
Hotti
Moin,
vor einem Jahr habe ich angefangen mir einen ORM selber zu basteln. Dabei war für mich wichtig, das die stärken beider Systeme (also Datenbank und Objekt) ausgenutzt werden. Daraus entstand ein äußerst effektives Entity-Objekt model, dass bis heute sehr einfach sehr gute Dienste leistet.
Es dreht sich dabei alles um die Entitys, welche bei mir Objekte sind. Eine Entity hat als Konstante alle Felder der Datenbank drin. Somit dient es gleichzeitig als Abstraktionsschicht, falls sich die Datenbank bzw. die Feldernamen ändern. Dreh und angelpunkt ist ebenfalls die Vererbung des ArrayObjectes. Das ist eine Mischform zwischen Objekt und Array.
Ein Beispiel:
class cEntity extends ArrayObject
{
const nameTableName = "TABLE";
const nameKeyName = "TABLE_ID";
const nameField = "FIELD";
public function method(){}
}
$objEntity = new cEntity();
$objEntity[$objEntity::nameField] = "Value";
echo $objEntity[$objEntity::nameField]; //--- Value
Wie man sieht entfallen hier komplett die get und setter Methoden. Vorteil man muss weniger Methoden definieren. Nachteil, mann muss für jedes Feld eine Konstante definieren.
Dazu habe ich mir noch eine Abstraktionsebene vom PDO Objekt gebastelt. Das spuckt mir bei einer Datenbankabfrage die Entitys als Objekte aus.
Ein weiterer Vorteil ist, dass die jede ein oder ausgabe über eine Methode läuft offsetGet und offsetSet. Möchte man also einen Wert überprüfen oder abfangen, kann man das in diesen zwei magischen Methoden machen.
Soweit ein kleiner Einblick. Wenn interesse besteht kann ich gern mehr Erläutern.
Gruß
MRO MOR ROM RMO OMR ORM (na endlich)
T-Rex
Tach!
class cEntity extends ArrayObject
{
const nameTableName = "TABLE";
const nameKeyName = "TABLE_ID";
const nameField = "FIELD";
public function method(){}
}$objEntity = new cEntity();
$objEntity[$objEntity::nameField] = "Value";
echo $objEntity[$objEntity::nameField]; //--- Value
Deine Schreibweise dürfte einen Syntaxfehler liefern. Konstanten gehören zur Klasse, also sollten/müssen sie über den Klassenamen angesprochen werden.
$objEntity[cEntity::nameField] = "Value";
echo $objEntity[cEntity::nameField]; //--- Value
Ein weiterer Vorteil ist, dass die jede ein oder ausgabe über eine Methode läuft offsetGet und offsetSet. Möchte man also einen Wert überprüfen oder abfangen, kann man das in diesen zwei magischen Methoden machen.
Eigentlich sind das ja keine magischen Methoden. Diese Bezeichnung ist einigen der mit __ beginnenden vorbehalten. Aber letztlich werden sie auch auf für den Anwender verdeckte Weise aufgerufen. Wie auch immer, die Schreibweise über eine Klassenkonstante ist nicht so einfach wie ein Eigenschaftenzugriff: $object->property. Das könntest du mit den magischen Methoden __get/__set hinbekommen. Die lässt du nur Werte für die Eigenschaften behandeln, die in einer Liste definiert sind.
dedlfix.
Deine Schreibweise dürfte einen Syntaxfehler liefern. Konstanten gehören zur Klasse, also sollten/müssen sie über den Klassenamen angesprochen werden.
Nö seit PHP 5.3.blub funktioniert dass. Ich hab da auf jedenfall keine Probleme damit. Als ich das System mal "irrtümlich" (wie das klingt :D) auf einem 5.2.x System installiert hab gabs jedoch tatsächlich Probleme.
Ja das mit den Public Variablen hab ich mir auch gedacht, wollte aber eine klare Abgrenzung zwischen Tabellenfeldern und allem anderen was noch so zur Klasse gehört. Deshalb habe ich mich für Konstante entschieden. Achja Konstante kann man auch nicht überschreiben. Bei Public Variablen muss man auf jeden Fall die __set Methode bearbeiten, damit man nichts überschreibt. Bislang hab ich da auch noch keine Probleme gehabt.
Gruß
der mit zu wenig Blut im Kreislauf
T-Rex
Tach!
Deine Schreibweise dürfte einen Syntaxfehler liefern. Konstanten gehören zur Klasse, also sollten/müssen sie über den Klassenamen angesprochen werden.
Nö seit PHP 5.3.blub funktioniert dass. Ich hab da auf jedenfall keine Probleme damit. Als ich das System mal "irrtümlich" (wie das klingt :D) auf einem 5.2.x System installiert hab gabs jedoch tatsächlich Probleme.
Da hast du Recht. Da kommt nicht mal mehr eine E_STRICT-Meldung. Als empfehlenswert sehe ich das aber nicht an. PHP ist zwar PHP mit all seinen Eigenarten, aber üblicherweise spricht man solche Konstanten in anderen Sprachen auch über den Klassennamen an. Ich denke, es ist besser, diese Notwendigkeit anderenorts hier als Konvention beizubehalten.
dedlfix.
Da hast du Recht. Da kommt nicht mal mehr eine E_STRICT-Meldung. Als empfehlenswert sehe ich das aber nicht an. PHP ist zwar PHP mit all seinen Eigenarten, aber üblicherweise spricht man solche Konstanten in anderen Sprachen auch über den Klassennamen an. Ich denke, es ist besser, diese Notwendigkeit anderenorts hier als Konvention beizubehalten.
Da hast du wiederum Recht ;). Meistens beherzige ich das auch. Hier und da verlockt jedoch gerade ein schnelles Copy und Paste dazu, die Instanz zu benutzen. Dann spielt der Klassenname keine Rolle und man kann (wenn die Konstante ebenfalls gleich heißt) eventuell einen kompletten Block kopieren. Wobei das jetzt nach mehr Redundanzen klingt als wirklich vorhanden sind :D.
Gruß
Redundanter
T-Rex T-Rex T-Rex T-Rex T-Rex
hi,
Wie man sieht entfallen hier komplett die get und setter Methoden. Vorteil man muss weniger Methoden definieren. Nachteil, mann muss für jedes Feld eine Konstante definieren.
Du greifst über die Instanz direkt auf die Attribute zu. Freilich können Getter/Setter dabei entfallen, das bringt jedoch nur Nachteile, der entscheidende Nachteil ist, dass Deine Klasse nicht vom Code abstahiert ist, etwaige Änderungen in der Klasse betreffen dann auch den Code.
Hotti
Du greifst über die Instanz direkt auf die Attribute zu. Freilich können Getter/Setter dabei entfallen, das bringt jedoch nur Nachteile, der entscheidende Nachteil ist, dass Deine Klasse nicht vom Code abstahiert ist, etwaige Änderungen in der Klasse betreffen dann auch den Code.
Die Bedenken hatte ich am Anfang auch. Aber ob du jetzt einen Methodennamen änderst oder einen Konstantennamen ist das gleiche. Ergo habe ich bei den Konstanten auch das OOP Prinzip "offen für Erweiterung und geschlossen für Änderung" eingeführt.
Das wäre auch noch ein Grund wieso ich Konstanten gewählt habe und keine Public Variablen.
Gruß
geschlossener
T-Rex
hi,
Das wäre auch noch ein Grund wieso ich Konstanten gewählt habe und keine Public Variablen.
Mal unabhängig davon: Ich stelle mir, von Perl kommend, gerade die Frage nach dem Sinn von Public-Variables:
In Perl sind alle Attribute einer Klasseninstanz "public", jeder kann darauf zugreifen, macht aber keiner ;)
Genausowenig nutzt in Perl keiner als 'private' gekennzeichnete Methoden, obwohl das grundsätzlich auch möglich ist.
Der Grund ist der: Disziplin und Abstraktion. Der Author einer Klasse könnte diese intern total umbauen, andere Attribute, andere private Methoden. Nach einem Update funktioniert dann der Code nicht mehr, er würde jedoch weiterhin funktionieren, wenn die dokumentierte API (public) genutzt wird.
Public-Vars sind tückisch, wenn sie klassenintern einer Rolle spielen, noch tückischer ist es, solche Variablen über eine Klassenmethode zu setzen, eine diesbezügliche Fehlersuche frisst unnötige Zeit (es müssen aufwendige Backtraces gemacht werden, Logfile-Beobachtung usw.) und im produktiven Umfeld ist sowas tödlich.
Hotti
Hallo,
Wie andere schon geschrieben haben beschreibst du ein ORM, ich wollte noch dazu sagen dass es da schon einiges fertig gibt das man sich unbedingt anschauen sollte bevor man das Rad zum x-ten mal neu erfindet, für PHP z.b. http://www.propelorm.org/
Jeena