ERLEDIGT
NEIN
NEIN
ANTWORTEN
2
2
ZUGRIFFE
495
495
EMPFEHLEN
-
18.08.10 18:13 #1
- Registriert seit
- May 2007
- Ort
- Dresden (Sachsen)
- Beiträge
- 1.961
Guten Tag Tutorianer,
ich habe gerade ein kleines, vielleicht sogar großes, Problem mit den magischen Methoden __set() und __get(). Warum, dass erkläre ich euch jetzt: ich arbeite momentan an einem ActiveRecord-Framework und noch momentaner an der Modelklasse. Dabei gibt es sogenannte Setter und Getter, mit welchen man die Eigenschaften eines Datensatzes abfragen kann und auch verändern kann. Soweit ist das kein Problem, allerdings soll man auch die Möglichkeit haben, dass beispielsweise beim Speichern eines Kennwortes dieses gleich beim Festlegen in einen SHA1-Hash umwandeln. Das ist auch nicht das Problem, denn das erledige ich über Methoden, welche mit "set_" oder "get_" anfangen und dann der Name der Eigenschaft folgt. Jetzt kommt aber das Problem: will man nun gleich die Eigenschaft mit dem gleichen Namen überschreiben, so wird das in den meisten Frameworks darüber gelöst, dass man zwei weitere Methoden, write_attribute() und read_attribute(), hat mit welchen man den Wert überschreiben kann. Das will ich nicht, sondern ich will die magischen Methoden von PHP auch an dieser Stelle verwenden können, nur leider funktioniert dies nur halbherzig und ohne meinerseits erkenntliche Logik. Vielleicht seht ihr wo der Fehler liegt.
So wird es meistens gelöst:
Code PHP:1 2 3
function set_password($password) { $this->write_attribute('password', $password); }
So will ich es lösen:
Code PHP:1 2 3
function set_password($password) { $this->password = $password; }
Was ich bisher habe:
Code PHP:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
class XtModelStorage { private static $storage = array(); public static function setGetter($model, array $attributes) { if(!isset(self::$storage[$model]['getter'])) self::$storage[$model]['getter'] = $attributes; } public static function setSetter($model, array $attributes) { if(!isset(self::$storage[$model]['setter'])) self::$storage[$model]['setter'] = $attributes; } public static function getGetter($model) { if(isset(self::$storage[$model]['getter'])) return self::$storage[$model]['getter']; return null; } public static function getSetter($model) { if(isset(self::$storage[$model]['setter'])) return self::$storage[$model]['setter']; return null; } public static function hasGetter($model, $name) { return (isset(self::$storage[$model]['getter']) && in_array($name, self::$storage[$model]['getter'])); } public static function hasSetter($model, $name) { return (isset(self::$storage[$model]['setter']) && in_array($name, self::$storage[$model]['setter'])); } public static function getList() { return self::$storage; } } class XtModel { private static $attributes = array(); private static $temp = false; final public function __construct() { $setter = array(); $getter = array(); $methods = XtClass::create(get_called_class())->getMethods(); foreach($methods as $method) { if($method->name[0] === '_') continue; @list($prefix, $attribute) = explode('_', $method->name, 2); if($prefix === 'set') $setter[] = $attribute; elseif($prefix === 'get') $getter[] = $attribute; } XtModelStorage::setGetter(get_called_class(), $getter); XtModelStorage::setSetter(get_called_class(), $setter); } final public function __set($attribute, $value) { $called = get_called_class(); if(!self::$temp && XtModelStorage::hasSetter($called, $attribute)) { self::$temp = true; $this->{'set_' . $attribute}($value); return; } self::$attributes[$called][$attribute] = $value; self::$temp = false; } final public function __get($attribute) { $called = get_called_class(); return self::$attributes[$class][$attribute]; } } class Test extends XtModel { function set_password($password) { $this->password = sha1($password); } function set_username($username) { $this->username = strlen($username); } }
Was erledigen die einzelnen Klassen?- Klasse "XtModelStorage" speichert alle Getter- und Settermethoden von Klassen, welche von der Klasse "XtModel" erben
- Klasse "XtModel" enthält die gesamte Logik des Models, lädt also die Getter- und Settermethoden, speichert sie. Außerdem enthält es die Methoden __set() und __get()
- Klasse "Test" ist nur ein Beispiel
Wenn ein Attribut aufgerufen wird, zu dem eine Settermethode existiert, so werden die Werte an die entsprechende Settermethode weitergeleitet. Da diese auch die Methode __set() verwendet, wird vorher markiert, dass gerade eine solche Methode aufgerufen wurde. Das steckt in der Eigenschaft self::$temp. Falls self::$temp wahr ist, wird mit der Eigenschaft wie mit einer normalen Variable umgegangen und sie in der Eigenschaft self::$attributes gespeichert. Danach wird die Eigenschaft self::$temp wieder als falsch markiert. Soweit die Theorie - es funktioniert nur nicht.
PS: Auch wenn es um __set() und __get() geht, so möchte ich mich vorerst nur auf die Methode __set() beschränken.Ich mag:- positive Bewertungen meiner Beiträge
- ein Danke für meine hilfreichen Beiträge
Dabei kann ich dir helfen: PHP --- Javascript --- Ruby --- Coffeescript --- CSS --- HTML --- Webtechnologien --- Shell --- UNIX
... noch was: falls du mit dem Thema hier fertig bist, dann kannst du es auch als erledigt markieren.
-
Hi,
laut PHP-Doku - "__set() wird aufgerufen, wenn Daten in unzugreifbare Eigenschaften geschrieben werden sollen." Bei dir sind Properties nach dem ersten Aufruf zugreifbar ($this->password, $this->username), sprich die Methode __set wird dann nicht emhr ausgeführt. Du könntest das verhindern, indem du diese Properties als private definierst oder statt dessen in einem Property-Array vorhältst.
Was ich komisch finde, beim ersten Aufruf mittels Setter schreibst du den Wert nicht in self::$attributes[$called][$attribute] weg, liest beim Getter aber immer von dort aus. Ist das so gewollt?
Grüße
BNEine Lösung hätte ich schon, aber sie passt nicht zum Problem.
-
20.08.10 15:23 #3
- Registriert seit
- May 2007
- Ort
- Dresden (Sachsen)
- Beiträge
- 1.961
Ja, dass ist so gewollt, ist aber nur momentan so. Später wird es, wie schon oben genannt, auch Gettermethoden geben, welche dazwischen geschaltet werden können. Außerdem schreibe ich den Wert auch in dieses Array, allerdings erst beim zweiten Mal. Aber mir ist gerade etwas aufgefallen, was ich mal überprüfen sollte: in der Methode __set() verwende ich die Variable $called und bei __get() die Variable $class, obwohl in beiden Fällen nur $called richtig ist.
Ich mag:- positive Bewertungen meiner Beiträge
- ein Danke für meine hilfreichen Beiträge
Dabei kann ich dir helfen: PHP --- Javascript --- Ruby --- Coffeescript --- CSS --- HTML --- Webtechnologien --- Shell --- UNIX
... noch was: falls du mit dem Thema hier fertig bist, dann kannst du es auch als erledigt markieren.
Ähnliche Themen
-
Post Methoden Problem
Von Xanoskar1 im Forum HTML & XHTMLAntworten: 1Letzter Beitrag: 28.12.10, 17:21 -
split()-Methoden problem
Von yax im Forum Java GrundlagenAntworten: 29Letzter Beitrag: 07.09.10, 18:13 -
Methoden Rückgabe Problem - PHP OOP
Von mkoeni1 im Forum PHPAntworten: 4Letzter Beitrag: 21.03.08, 17:55 -
Problem mir Methoden aufruf
Von chickenwings im Forum JavaAntworten: 6Letzter Beitrag: 04.12.06, 16:47 -
methoden problem
Von DevEye im Forum JavaAntworten: 8Letzter Beitrag: 26.11.05, 16:24






Zitieren
Login






[PHP][Snippet] Array zu XML konvertieren