tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
2
ZUGRIFFE
495
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Avatar von einfach nur crack
    einfach nur crack einfach nur crack ist offline mag Cookies & Kekse
    tutorials.de Premium-User
    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
    Was erledigt meine __set()-Methode?

    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.

  2. #2
    Avatar von bn
    bn bn ist offline Mitglied Brokat
    Registriert seit
    Oct 2002
    Ort
    Berlin
    Beiträge
    395
    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
    BN
     
    Eine Lösung hätte ich schon, aber sie passt nicht zum Problem.

  3. #3
    Avatar von einfach nur crack
    einfach nur crack einfach nur crack ist offline mag Cookies & Kekse
    tutorials.de Premium-User
    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

  1. Post Methoden Problem
    Von Xanoskar1 im Forum HTML & XHTML
    Antworten: 1
    Letzter Beitrag: 28.12.10, 17:21
  2. split()-Methoden problem
    Von yax im Forum Java Grundlagen
    Antworten: 29
    Letzter Beitrag: 07.09.10, 18:13
  3. Methoden Rückgabe Problem - PHP OOP
    Von mkoeni1 im Forum PHP
    Antworten: 4
    Letzter Beitrag: 21.03.08, 17:55
  4. Problem mir Methoden aufruf
    Von chickenwings im Forum Java
    Antworten: 6
    Letzter Beitrag: 04.12.06, 16:47
  5. methoden problem
    Von DevEye im Forum Java
    Antworten: 8
    Letzter Beitrag: 26.11.05, 16:24

Stichworte