1. Einfache Umwandlung mit (array)$object
Ein Objekt $object kann in den Datentyp Array umgewandelt werden, indem (array)$object angewendet wird. Das sich ergebende Array enthält dann alle nicht statischen Felder bzw. Variablen des Objekts — also auch solche, die als private oder protected markiert sind. Der Aufbau das Arrays ist grob „string Variablenname => mixed Wert”. Wie im nachfolgenden Beispiel zu sehen ist, sind die Namen von private und protected Variablen zusätzlich gekennzeichnet. Erstere durch den Klassennamen am Anfang, letztere durch einen Stern (*). Beide Markierungen sind jeweils noch von Sonderzeichen umgeben.
<?php class MyClass { private $v1 = 'beispiel1'; protected $v2 = 'beispiel2'; public $v3 = 'beispiel3'; public static $v4 = 'beispiel4'; const v5 = 'beispiel5'; var $v6 = 'beispiel6'; public function __construct() { $this->v7 = 'beispiel7'; } } $obj = new MyClass(); var_dump((array)$obj); ?>
array(5) { ["�MyClass�v1"]=> string(9) "beispiel1" ["�*�v2"]=> string(9) "beispiel2" ["v3"]=> string(9) "beispiel3" ["v6"]=> string(9) "beispiel6" ["v7"]=> string(9) "beispiel7" }
2. Welche Sonderzeichen werden in den Markierungen verwendet?
Das vorherige Beispiel lässt die Frage aufkommen, von welchen Sonderzeichen die Markierungen der mit private und protected gekennzeichneten Variablen umgeben sind. Dies lässt sich leicht herausfinden, indem ein mal ord() auf diese Zeichen angewendet wird. Im nachfolgenden Beispiel wird eine einfache Klasse mit nur einer privaten Variable definiert. Anschließend wird ein Objekt dieser Klasse erzeugt, welches sofort in ein Array umgewandelt wird. Der erste Schlüssel des Arrays (und damit derjenige der privaten Variable) wird mit key($arr) ermittelt. Nachdem der Schlüssel bekannt ist, erfolgt das Aufsplitten von diesem in einzelne Zeichen durch Anwendung von str_split(). Mit der Kombination von array_walk() und ord() wird die ASCII-Nummer jedes einzelnen Zeichens ermittelt. Über echo() und implode() erfolgt am Ende die Ausgabe der ASCII-Nummern als ein kommagetrennter String.
Wie in der Ausgabe zu erkennen ist, haben die Sonderzeichen jeweils die ASCII-Nummer 0.
<?php class Test { private $a = 'a'; } $arr = (array)new Test(); // ersten Key bestimmen reset($arr); $firstKey = key($arr); var_dump($firstKey); // Zeichen zu ASCII-Nummern $ords = array(); $splitted = str_split($firstKey); array_walk($splitted, function($letter) use (&$ords) { $ords[] = ord($letter); }); echo(implode(', ', $ords)); ?>
string(7) "�Test�a" 0, 84, 101, 115, 116, 0, 97
3. Test mit "von außen" gesetzten Variablen und Variablennamen mit Sonderzeichen
Im nächsten Beispiel wird geprüft, wie sich die Umwandlung von Objekt zu Array per (array) verhält, wenn zuvor von „außerhalb” des Objekts Variablen gesetzt wurden. Eine der beiden gesetzten Variablen hat einen normalen Namen („v8”), einer besteht nur aus Sonderzeichen. Wie anhand der Ausgabe zu erkennen ist, werden beide Variablen bei der Umwandlung korrekt übernommen.
<?php class MyClass { private $v1 = 'beispiel1'; protected $v2 = 'beispiel2'; public $v3 = 'beispiel3'; public static $v4 = 'beispiel4'; const v5 = 'beispiel5'; var $v6 = 'beispiel6'; public function __construct() { $this->v7 = 'beispiel7'; } } $obj = new MyClass(); $obj->v8 = 'beispiel8'; $obj->{'+$%#'} = 'test'; var_dump((array)$obj); ?>
array(7) { ["�MyClass�v1"]=> string(9) "beispiel1" ["�*�v2"]=> string(9) "beispiel2" ["v3"]=> string(9) "beispiel3" ["v6"]=> string(9) "beispiel6" ["v7"]=> string(9) "beispiel7" ["v8"]=> string(9) "beispiel8" ["+$%#"]=> string(4) "test" }
4. Umwandlung mit foreach-Schleife
Die Variablen eines Objekts können auch per foreach-Schleife ausgelesen werden. Dazu wird das Objekt wie ein Array behandelt und einfach darüber iteriert. Im Gegensatz zur gezielten Umwandlung mit (array) werden diesmal aber nur die öffentlichen (public) Felder erfasst.
<?php class MyClass { private $v1 = 'beispiel1'; protected $v2 = 'beispiel2'; public $v3 = 'beispiel3'; public static $v4 = 'beispiel4'; const v5 = 'beispiel5'; var $v6 = 'beispiel6'; public function __construct() { $this->v7 = 'beispiel7'; } } $obj = new MyClass(); $out = array(); foreach ($obj as $key=>$val) { $out[$key] = $val; } var_dump($out); ?>
array(3) { ["v3"]=> string(9) "beispiel3" ["v6"]=> string(9) "beispiel6" ["v7"]=> string(9) "beispiel7" }
5. Mit current(), key() und next()
Ebenfalls zum Auslesen des Objekts können die Funktionen current($arr), key($arr) und next($arr) verwendet werden. Entsprechend der Parameter sollen diese eigentlich auf Arrays angewendet werden, eignen sich aber auch für Objekte. Über next($obj) kann der interne Zeiger auf die nächste Variable im Objekt $obj gesetzt werden. Mit current($obj) wird der Wert dieser Variable ausgelesen, mit key($obj) analog deren Name. Mit einer kurzen while-Schleife kann nun über alle Variablen iteriert werden. Jeder einzelne Schlüssel und Wert werden dann in einem Ausgabearray ($out) zwischengespeichert. Im Gegensatz zur foreach-Schleife ermittelt diese Methode auch private und protected Variablen des Objekts.
<?php class MyClass { private $v1 = 'beispiel1'; protected $v2 = 'beispiel2'; public $v3 = 'beispiel3'; public static $v4 = 'beispiel4'; const v5 = 'beispiel5'; var $v6 = 'beispiel6'; public function __construct() { $this->v7 = 'beispiel7'; } } $obj = new MyClass(); $out = array(); while (current($obj)) { $out[key($obj)] = current($obj); next($obj); } var_dump($out); ?>
array(5) { ["�MyClass�v1"]=> string(9) "beispiel1" ["�*�v2"]=> string(9) "beispiel2" ["v3"]=> string(9) "beispiel3" ["v6"]=> string(9) "beispiel6" ["v7"]=> string(9) "beispiel7" }
6. Eigene Funktion zur Umwandlung von Objekt zu Array
Im nächsten Beispiel wird die Funktion „objToArray($obj)” definiert. Diese nimmt ein Objekt entgegen und konvertiert dieses in ein Array. Dazu wird die Umwandlung per (array)$obj verwendet. Das Ergebnis dieser Umwandlung wird aufbereitet, sodass die Schlüssel das Arrays den Namen der Variablen entsprechen (auch bei private und protected Variablen). Die Werte wiederum sind ebenfalls Arrays, welche zum einen den Wert der Variablen (Index 0) und die Sichtbarkeit (Index 1, „private” oder „protected” oder „public”) enthalten. Der Aufbau ist also grob: array(string Variablenname => array(mixed Variablenwert, string "private"/"protected"/"public")).
<?php class MyClass { private $v1 = 'beispiel1'; protected $v2 = 'beispiel2'; public $v3 = 'beispiel3'; public static $v4 = 'beispiel4'; const v5 = 'beispiel5'; var $v6 = 'beispiel6'; public function __construct() { $this->v7 = 'beispiel7'; } } function objToArray($obj) { if (!is_object($obj)) { throw new Exception('Object expected, got '.gettype($obj).'.'); } $clazz = get_class($obj); // Name der Klasse des uebergebenen Objekts $privateStart = chr(0) . $clazz . chr(0); // Start jedes Namens einer privaten Variablen $protectedStart = chr(0) . '*' . chr(0); // Start jedes Namens einer protected Variablen $arr = (array)$obj; $out = array(); foreach ($arr as $key=>$val) { if (strpos($key, $privateStart)===0) { // private Variable $out[ substr($key, strlen($privateStart)) ] = array($val, 'private'); } else if (strpos($key, $protectedStart)===0) { // protected Variable $out[ substr($key, strlen($protectedStart)) ] = array($val, 'protected'); } else { // public Variable $out[ $key ] = array($val, 'public'); } } return $out; } $obj = new MyClass(); var_dump( objToArray($obj) ); ?>
array(5) { ["v1"]=> array(2) { [0]=> string(9) "beispiel1" [1]=> string(7) "private" } ["v2"]=> array(2) { [0]=> string(9) "beispiel2" [1]=> string(9) "protected" } ["v3"]=> array(2) { [0]=> string(9) "beispiel3" [1]=> string(6) "public" } ["v6"]=> array(2) { [0]=> string(9) "beispiel6" [1]=> string(6) "public" } ["v7"]=> array(2) { [0]=> string(9) "beispiel7" [1]=> string(6) "public" } }
7. Auslesen mit Reflection
Auch das Prinzip der Reflection kann genutzt werden, um ein Objekt auszulesen. Dazu wird zunächst eine ReflectionClass des Objekts mit „new ReflectionClass($obj)” erzeugt. Dieses neue Reflection-Objekt bietet nun etliche Methoden an, um das zugrundeliegende Objekt $obj zu analysieren. Wir sind an dieser Stelle nur an den Feldern des Objekts interessiert und verwenden daher die Methode getProperties(), die von ReflectionClass angeboten wird und alle Felder in Form eines Arrays von ReflectionProperty zurückgibt. Über dieses Array kann mit einer simplen foreach-Schleife iteriert werden. Jedes Feld (bzw. ReflectionProperty) bietet nun unter anderem die Methoden isStatic(), isPrivate(), isProtected() und isPublic() an, über die die Sichtbarkeit des Feldes (statisch, privat, protected, public) ermittelt werden kann. Mit den Methoden getName() und getValue() werden Name und Wert der Variablen ausgelesen. Vor der Verwendung dieser Methoden muss noch ein mal „setAccessible(true)” auf das ReflectionProperty angewendet werden, sonst bekommt man Probleme mit privaten/protected Variablen.
<?php class MyClass { private $v1 = 'beispiel1'; protected $v2 = 'beispiel2'; public $v3 = 'beispiel3'; public static $v4 = 'beispiel4'; const v5 = 'beispiel5'; var $v6 = 'beispiel6'; public function __construct() { $this->v7 = 'beispiel7'; } } function objToArrayReflection($obj) { if (!is_object($obj)) { throw new Exception('Object expected, got '.gettype($obj).'.'); } // neue ReflectionClass des Objekts bilden $clazz = new ReflectionClass($obj); // Alle Felder bzw. Variablen des Objekts auslesen // Die Parameter waeren nicht notwendig und werden hier nur uebergeben, um zu // zeigen, dass die Rueckgabe eingeschraenkt werden kann $properties = $clazz->getProperties( ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_STATIC ); $out = array(); // Ueber alle Felder bzw. Variablen des Objekts iterieren foreach ($properties as $property) { // Problemen bei private/protected vorbeugen $property->setAccessible(true); // ist das Feld statisch (static)? $static = $property->isStatic(); // Sichtbarkeit des Feldes bestimmen (private, protected, public) $access = ($property->isPrivate() ? 'private' : ($property->isProtected() ? 'protected' : 'public')); // Name des Feldes, Wert des Feldes, Sichtbarkeit und "statisch?"-Angabe // zum Rueckgabearray hinzufuegen $out[$property->getName()] = array($property->getValue($obj), $access, $static); } return $out; } $obj = new MyClass(); var_dump( objToArrayReflection($obj) ); ?>
array(5) { ["v1"]=> array(3) { [0]=> string(9) "beispiel1" [1]=> string(7) "private" [2]=> bool(false) } ["v2"]=> array(3) { [0]=> string(9) "beispiel2" [1]=> string(9) "protected" [2]=> bool(false) } ["v3"]=> array(3) { [0]=> string(9) "beispiel3" [1]=> string(6) "public" [2]=> bool(false) } ["v4"]=> array(3) { [0]=> string(9) "beispiel4" [1]=> string(6) "public" [2]=> bool(true) } ["v6"]=> array(3) { [0]=> string(9) "beispiel6" [1]=> string(6) "public" [2]=> bool(false) } }