Objekt in Array umwandeln – wird eine magische Methode aufgerufen?
Lesezeit: 7 Minuten
Ich habe ein Objekt der Klasse Foo:
class Foo extends Bar {
protected $a;
protected $b;
}
$obj = new Foo();
Was ich tun möchte (und muss), ist dieses Objekt in ein Array umzuwandeln, wie folgt:
$arr = (array)$obj;
Gibt es eine magische (oder nicht magische :)) Methode, die gerade aufgerufen wird? Oder gibt es eine andere Möglichkeit, es abzufangen? Ich weiß, dass ich eine einfache Methode schreiben kann, z. asArray() in Foo, aber ich suche nach mehr “nativen” PHP-Möglichkeiten.
Sehen Sie, wir haben __toString, da es in Sprachkonstrukten wie echo, print und anderen internen Funktionen unterstützt wird. Aber wir haben uns bereits gegen eine Autokonvertierung für Arrays entschieden. Daher wird es in keinem Sprachkonstrukt unterstützt. Das heißt, es wird nichts dafür benötigt und nichts, was Sie gegen die obige Schnittstelle gewinnen würden. Tatsächlich würden Sie es php komplexer machen, weil Sie nur eine weitere magische Funktion hinzufügen würden.
Es ist daher sehr unwahrscheinlich, dass es in einer zukünftigen Version implementiert wird (was schade ist, wenn Sie mich fragen).
Aber hey, haben wir nicht wenigstens das goto-Konstrukt bekommen? zittert
– Tacon
27. Dezember 2013 um 13:16 Uhr
Es ist seltsam, dass er das sagt, denn PHP hat tatsächlich eine Objekt-zu-Array-Konvertierung: php.net/manual/en/…
– Stirb jetzt
21. Januar 2014 um 15:03 Uhr
Die Frage bezieht sich eigentlich darauf, benutzerdefinierte Casting-Logik implementieren zu können.
Sie können die Klasse implementieren lassen ArrayAccess Schnittstelle. Dadurch können Sie das Objekt ohne Umwandlung wie ein Array behandeln und erhalten die vollständige Kontrolle darüber, wie die Mitglieder verwendet werden.
Obwohl nett, geht diese Antwort nicht wirklich auf die Frage ein. Sie sollten zumindest das Wort “nein” irgendwo einfügen 🙂
– Hubro
29. April 2013 um 8:39 Uhr
Guter Punkt, aber geben Sie irgendwo am Anfang der Antwort an, dass die Implementierung der ArrayAccess Die Schnittstelle reicht nicht aus, um ein Objekt in ein Array umzuwandeln.
– Daniel Orlando
22. Dezember 2015 um 0:38 Uhr
Es sollte auch beachtet werden, dass sich das Objekt erstreckt, um Elemente zu durchlaufen, die in dem Objekt enthalten sind ArrayAccess verwenden foreachmüssen Sie ebenfalls implementieren \IteratorAggregate oder \Iterator. Im Allgemeinen diejenigen, die die Array-Funktionalität innerhalb eines Objekts reproduzieren möchten implements \Countable, \IteratorAggregate, \ArrayAccess Sehen \ArrayObject.
– Wird B.
22. Januar 2016 um 15:31 Uhr
Leider nein, das Casting in ein Array löst keine magische Methode aus, wie es mit:
$s = (string)$obj;
was auslöst __toString() -Methode, die Sie überschreiben können.
Sie können jedoch eine benutzerdefinierte schreiben toArray() Methode.
Das könnte Sie auch interessieren Serializable Schnittstelle, mit der Sie eine benutzerdefinierte Serialisierungsstrategie schreiben können.
Nicht sicher, ob diese Frage noch relevant ist, aber PHP hat eingebaut ArrayObject Klasse, die es ermöglicht, ein Objekt als Array zu behandeln, und kann praktisch sein, wenn es als Container für Datenbankeinträge oder -sammlungen verwendet wird.
Dies ist möglicherweise keine bewährte Methode in Bezug auf strikte Typen, ermöglicht jedoch die Behandlung von Objekten als Array, und beide Anweisungen sind gültig.
$obj = new ArrayObject(['a' => 'alpha']);
var_dump($obj['a']); //alpha
var_dump($obj->getOffset('a'));//alpha
Allerdings müssen Sie das Verhalten von im Auge behalten ArrayObject
ArrayObject akzeptiert zwei Flags ArrayObject::STD_PROP_LIST als Standard und ArrayObject::ARRAY_AS_PROPS als Alternative.
Dies würde das Verhalten beim Lesen von Werten ändern, unterstützt jedoch nicht das Festlegen neuer Eigenschaften auf diese Weise. Hier ist ein Beispiel:
Um dieses Verhalten konsistenter zu machen, müssten Sie diese Klasse erweitern und magische Methoden implementieren __get(), __set(), __isset() und __unset().
Ein weiterer kniffliger Teil ist die Serialisierung, die Standardmethode serialize würde Ihnen eine Kopie mit Seriennummer zurücksenden $storage Variable anstelle des Objekts selbst, als Problemumgehung, um eine serialisierte Kopie der Instanz zurückzugeben, in der Sie die Standardserialisierung implementieren können __toString Methode, auf diese Weise verhält es sich richtig.
class FooObject extends ArrayObject
{
public function __get($index)
{
if ($this->offsetExists($index)) {
return $this->offsetGet($index);
} else {
throw new UnexpectedValueException('Undefined key ' . $index);
}
}
public function __set($index, $value)
{
$this->offsetSet($index, $value);
return $this;
}
public function __isset($index)
{
return $this->offsetExists($index);
}
public function __unset($index)
{
return $this->offsetUnset($index);
}
public function __toString()
{
return serialize($this);
}
}
Eine Möglichkeit, dies zu tun, ohne die ursprüngliche Klassendefinition zu ändern, ist die Verwendung von Reflektion. Dadurch können Sie die Eigenschaften der Klasse zur Laufzeit untersuchen.
<?php
class Foo {
public $foo = 1;
protected $bar = 2;
private $baz = 3;
}
$foo = new Foo();
$reflect = new ReflectionClass($foo);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);
foreach ($props as $prop) {
print $prop->getName() . "\n";
}
var_dump($props);
?>
The above example will output something similar to:
foo
bar
array(2) {
[0]=>
object(ReflectionProperty)#3 (2) {
["name"]=>
string(3) "foo"
["class"]=>
string(3) "Foo"
}
[1]=>
object(ReflectionProperty)#4 (2) {
["name"]=>
string(3) "bar"
["class"]=>
string(3) "Foo"
}
}
Aghanim
Sie können get_object_vars($yourObject) verwenden, das ein assoziatives Array aller Eigenschaftsnamen/-werte zurückgibt, auf die aus dem Kontext zugegriffen werden kann.
Wenn Sie auf geschützte oder private Eigenschaften zugreifen möchten, wäre mein Rat, ArrayObject zu erweitern, das die Methode getArrayCopy() implementiert.
12829800cookie-checkObjekt in Array umwandeln – wird eine magische Methode aufgerufen?yes