Objekte persistent speichern / Reflection API / Private Attributes

expone

Mitglied
Hallo Zusammen!

Ich taste mich gerade an die Reflection API von PHP heran.
Ziel soll es sein, dass ich ausgewählte Objekte persistent in die Datenbank speichern kann.

Die erste Idee war dabei, dass ich mir alle Attribute eines Objektes nehme und deren Wert in die Datenbank speichere.

Dabei bin ich aber auf das Problem gestoßen, dass man keine Private-Member-Attribute außerhalb eines Objektes auslesen kann.

Meine nächste Idee wäre, dass ich alle Attributte über Getter und Setter erreichbar mache und die Benamung dieser Methoden einer Konvention unterwerfe. Ist der Name eines Getters bzw. eines Setter entsprechend, wird versucht via Reflection API die Werte auszulesen und zu setzen.

Diesen Weg halte ich aber für recht aufwändig.

Deshalb wollte ich hier allgemein mal von Euch Tipps zu diesem Thema sammeln.

Wie würdet ihr hier vorgehen?
 
Genau so will ich das eigentlich haben, gerne auch in abgespeckter Version...

Hibernate funktioniert allerdings nicht für PHP.
 
Erst einmal Danke für allen bisherigen Anregungen.

@katosan:
Dieses Propel scheint nicht auf einem Standard-PHP bzw. Apache Server zu laufen, sondern benötigt wohl die Torque-Erweiterung von Apache. Ich brauche eine reine PHP-Lösung, auch OHNE ZEND etc...

@R00Ki3:
Diese Magic-Methods nutzen mir in diesem Fall nichts. __GET und __SET Lösungen dienen nur dazu, nicht definierte Attribute aufrufen zu können, die dann in einem Array gemanaged werden... Für was auch immer man das brauchen mag ;)

@ALL
Ich habe mir nun folgende Lösung angeschaut: Ich habe eine Super-Parent-Klasse, von der ich alle weiteren Objekte ableite. Diese ist eine Erweiterung der Klasse ReflektionObject.

Wenn ich eine Klasse also von der Super-Parent-Klasse ableite, dann besitzt diese alle Eigenschaften und Methoden von ReflectionObject. Über diese geerbte Funktionalität kann ich also alle Attribut-Namen auslesen. Bleibt das Problem, dass mit bei der Methode ReflectionObject->getValue($obj, $AttrName) immer noch ein Objekt angeben muss. Dadurch geschieht ein Aufruf auf das Attribut von außerhalb des Objektes. Dies ist aber nicht möglich, wenn das Attribut mit private deklariert wurde.

Der Workaround sollte wie folgt aussehen: Ich implementiere in meiner Super-Parent-Klasse einfach zwei Methoden:

PHP:
    function getAttributeValue($p_sAttrName)
    {
        $x = "";
        eval('$x=$this->' . $p_sAttrName . ";");
        return $x;
    }


PHP:
    function setAttributeValue($p_sAttrName, $p_sAttrValue)
    {
        if (gettype($p_sAttrValue) == "string") { $p_sAttrValue = '"' . $p_sAttrValue . '"'; }
         eval('$this->' . $p_sAttrName . ' = '.$p_sAttrValue.';');
    }

Da diese Methoden von dem Objekt geerbt werden, von dem ich die Attributswerte auslesen und setzen möchte, und damit die oben gepostete Funktionalität auf dem aktuellen Objekt ausgeführt wird, sollte das Private-Problem umgangen sein.

Leider ist dem nicht so.

Wenn ich die Methode direkt in der Klasse implementiere, von dessen Objekt ich die Attribute auslesen will, dann funktioniert das ganze. Sobald die Methoden durch eine Vererbung ihren Weg in die Klasse finden, funktioniert das wiederum nicht.

Hier mal ein komplettes Code-Beispiel. Hoffe ich erschlage Niemanden:
PHP:
 <?php


/**
 * Central base clas
 */
class super_parent_class extends ReflectionObject {
    function getAttributeValue($p_sAttrName)
    {
        $x = "";
        eval('$x=$this->' . $p_sAttrName . ";");
        return $x;
    }
    
    function setAttributeValue($p_sAttrName, $p_sAttrValue)
    {
        if (gettype($p_sAttrValue) == "string") { $p_sAttrValue = '"' . $p_sAttrValue . '"'; }
         eval('$this->' . $p_sAttrName . ' = '.$p_sAttrValue.';');
    }
}

class myClass extends super_parent_class {
    private $attrPrivate = "Streng Geheim!";
    public $attrPublic = "Offen wie ein Buch.";
}

$memberCounter = 0;
$objectOfMyTest = new myClass();
$reflectionForMyClass = new ReflectionObject($objectOfMyTest);
$properties = $reflectionForMyClass->getProperties();

while ($memberCounter < count($properties)) {
    $member = $properties[$memberCounter];
    
    echo "Get Attr: " . $member->getName()."<br>";
    echo $member->getName() . "=" . $objectOfMyTest->getAttributeValue($member->getName()) . ";<hr>";

    $memberCounter++;
}
?>

Weiß Jemand warum das Problem bei der Vererbung auftaucht?
 
Mit eval ist aber ne extrem unsaubere lösung...
Und set und get hat einen leich anderen sinn...

Z.b.
PHP:
<?php
class test{
  private $private
  protected $protected
  public $pulbic
  public function __set($name, $value){
    if(isset($this->$name)){
      $this->$name = $value;
    }
  }
  public function __get($name){
    if(isset($this->$name)){
      return $this->$name;
    }
  }
}
Du kannst dir Werte ausgeben lassen egal welcher Typ (public, protected, private)...

Wenn du nun also alle bezeichnungen der Variablen kennst kannst du ohne Probleme
$this->$name aufrufen und du hast die werte....
 
Deins umgewandelt würde dann so aussehen...
PHP:
<?
class test{
    private $private;
    protected $protected;
    public $public
    public function __get($name){
        if(isset($this->$name)){
            return $this->$name;
        }
        return false;
    }
}

$test = new test();
$reflectionForMyClass = new ReflectionObject($test);
$properties = $reflectionForMyClass->getProperties(); 
for($i = 0; $i < count($properties); $i++){
    $member = $properties[$i];
    $name = $member->getName();
    echo "Get Attr: " . $name."<br>";
    echo $name . "=" . $test->$name.";<hr>";
}
?>
 
OK, vielen Dank und entschuldigt die späte Reaktion von mir. Hab etwas viel um die Ohren.

Werd mir heut Abend noch die Lösung genauer anschauen.
 
Zurück