So fügen Sie dem Objekt im strengen Modus PHP> = 5.3 eine Eigenschaft hinzu, ohne einen Fehler zu generieren

80

Das muss einfach sein, aber ich kann anscheinend keine Antwort finden ...

Ich habe ein generisches stdClass-Objekt $fooohne Eigenschaften. Ich möchte eine neue Eigenschaft hinzufügen $bar, die noch nicht definiert ist. Wenn ich das mache:

$foo = new StdClass();
$foo->bar = '1234';

PHP im strengen Modus beschwert sich.

Was ist der richtige Weg (außerhalb der Klassendeklaration), um einem bereits instanziierten Objekt eine Eigenschaft hinzuzufügen?

HINWEIS: Ich möchte, dass die Lösung mit dem generischen PHP-Objekt vom Typ stdClass funktioniert.

Ein kleiner Hintergrund zu diesem Thema. Ich decodiere eine JSON-Zeichenfolge, die ein Array von JSON-Objekten ist. json_decode()generiert ein Array von StdClass-Objekten. Ich muss diese Objekte manipulieren und jedem eine Eigenschaft hinzufügen.

Strahl
quelle
Versuchen Sie TRUEals 2. Parameter an zu übergeben json_decode. Sie erhalten ein assoziatives Array anstelle eines Arrays von Objekten.
Rocket Hazmat
1
PHP im strengen Modus beschwert sich darüber nicht. 3v4l.org/kn0hi
hakre
3
Ich weiß nicht, warum dies geschlossen wurde, da dies eine vollkommen gültige Frage ist. Ich habe gerade eine genau ähnliche Frage.
Steven

Antworten:

129

Wenn Sie die Eigenschaft unbedingt zum Objekt hinzufügen müssen, können Sie sie meiner Meinung nach als Array umwandeln, Ihre Eigenschaft (als neuen Array-Schlüssel) hinzufügen und dann als Objekt zurücksetzen. Das einzige Mal, stdClasswenn Sie auf Objekte stoßen (glaube ich), ist, wenn Sie ein Array als Objekt umwandeln oder wenn Sie ein neues stdClassObjekt von Grund auf neu erstellen (und natürlich, wenn Sie json_decode()etwas tun - dumm, dass ich es vergessen habe!).

Anstatt:

$foo = new StdClass();
$foo->bar = '1234';

Du würdest tun:

$foo = array('bar' => '1234');
$foo = (object)$foo;

Oder wenn Sie bereits ein vorhandenes stdClass-Objekt hatten:

$foo = (array)$foo;
$foo['bar'] = '1234';
$foo = (object)$foo;

Auch als 1 Liner:

$foo = (object) array_merge( (array)$foo, array( 'bar' => '1234' ) );
Crontab
quelle
1
Ein Ort, an dem Sie auf StdClass stoßen, ist das Dekodieren von json, was ziemlich häufig vorkommt.
Ray
1
@ Ray Ich schüttle traurig den Kopf, dass ich nicht daran gedacht habe, das zu erwähnen. =)
Crontab
3
Ihre Lösung funktioniert, aber es tut meinem OO-Herzen weh :) Ich habe auf eine Art auffälliges Reflexions-Kung-Foo gehofft oder so ... Ich werde die Frage etwas länger offen halten und auf etwas wenig bekannte PHP-Magie hoffen.
Ray
1
@ Ray hehehe ... Ich wünschte ich hätte etwas eleganteres für dich. Im übrigen ausdrücklich Einstellung error_reporting(E_STRICT);auf PHP 5.3.15-1~dotdeb.0 with Suhosin-Patch, ich bekomme keine Fehler oder Hinweise , wenn eine nicht vorhandene Eigenschaft auf einem stdClass Objekt zu setzen versucht. Welche Version von PHP verwenden Sie?
Crontab
Ha, fast drei Jahre später bekomme ich eine Drive-by-Abstimmung ohne Erklärung aus irgendeinem Grund. Vielen Dank.
Crontab
110

Mach es so:

$foo = new stdClass();
$foo->{"bar"} = '1234';

Versuchen Sie jetzt:

echo $foo->bar; // should display 1234
jmnerd
quelle
2
Wirkt als Charme. Dies sollte die akzeptierte Lösung sein.
Tarrakis
Wie können Sie einem Feld eines Objekts mit dieser Syntax eine Eigenschaft hinzufügen?
Big Money
'Versuch, die Eigenschaft eines
Nichtobjekts
Sogar die Zeichenfolge "bar" kann sich in einer Variablen befinden: $ foo -> {$ any_variable} = '1234';
Salar
Dies sollte definitiv die akzeptierte Antwort sein, da dadurch die Objektreferenz intakt bleibt (was in meinem Fall entscheidend war).
Johan Fredrik Varen
11

Wenn Sie den dekodierten JSON bearbeiten möchten, versuchen Sie, ihn als assoziatives Array anstelle eines Arrays von Objekten abzurufen.

$data = json_decode($json, TRUE);
Rakete Hazmat
quelle
2

Ich benutze immer so:

$foo = (object)null; //create an empty object
$foo->bar = "12345";

echo $foo->bar; //12345
Ragnar
quelle
1

Sie sollten magische Methoden __Set und __get verwenden. Einfaches Beispiel:

class Foo
{
    //This array stores your properties
private $content = array();

public function __set($key, $value)
{
            //Perform data validation here before inserting data
    $this->content[$key] = $value;
    return $this;
}

public function __get($value)
{       //You might want to check that the data exists here
    return $this->$content[$value];
}

}

Verwenden Sie dieses Beispiel natürlich nicht wie folgt: überhaupt keine Sicherheit :)

EDIT: Ihre Kommentare gesehen, hier könnte eine Alternative sein, die auf Reflexion und einem Dekorateur basiert:

 class Foo
 {
private $content = array();
private $stdInstance;

public function __construct($stdInstance)
{
    $this->stdInstance = $stdInstance;
}

public function __set($key, $value)
{
    //Reflection for the stdClass object
    $ref = new ReflectionClass($this->stdInstance);
    //Fetch the props of the object

    $props = $ref->getProperties();

    if (in_array($key, $props)) {
        $this->stdInstance->$key = $value;
    } else {
        $this->content[$key] = $value;
    }
    return $this;
}

public function __get($value)
{
    //Search first your array as it is faster than using reflection
    if (array_key_exists($value, $this->content))
    {
        return $this->content[$value];
    } else {
        $ref = new ReflectionClass($this->stdInstance);

        //Fetch the props of the object
        $props = $ref->getProperties();

        if (in_array($value, $props)) {

        return $this->stdInstance->$value;
    } else {
        throw new \Exception('No prop in here...');
    }
}
 }
}

PS: Ich habe meinen Code nicht getestet, nur die allgemeine Idee ...

Benjamin Dubois
quelle
3
Benjamin, ich möchte die generische Objektklasse von PHP verwenden: StdClass. Ich kann diese Klasse nicht ändern.
Ray
Ray, ich habe meine Antwort mit einer Lösung aktualisiert, die Ihrem Bedarf entspricht, aber es ist schwer: - /
Benjamin Dubois
1

Ich weiß nicht, ob es die neuere Version von PHP ist, aber das funktioniert. Ich benutze PHP 5.6

    <?php
    class Person
    {
       public $name;

       public function save()
       {
          print_r($this);
       }
    }

   $p = new Person;
   $p->name = "Ganga";
   $p->age = 23;

   $p->save();

Das ist das Ergebnis. Die Speichermethode erhält tatsächlich die neue Eigenschaft

    Person Object
    (
       [name] => Ganga
       [age] => 23
    )
Ganga
quelle
Ich habe mehrere Tests für den Code in PHP-Versionen durchgeführt und das Ergebnis zeigt, dass er nur für PHP 5 und höher funktioniert. Jede Version unter PHP5 gibt einen Fehler aus.
Big Tree
-6

Ja, es ist möglich, einem PHP-Objekt dynamisch Eigenschaften hinzuzufügen.

Dies ist nützlich, wenn ein Teilobjekt aus Javascript empfangen wird.

JAVASCRIPT Seite:

var myObject = { name = "myName" };
$.ajax({ type: "POST", url: "index.php",
    data: myObject, dataType: "json",
    contentType: "application/json;charset=utf-8"
}).success(function(datareceived){
    if(datareceived.id >= 0 ) { /* the id property has dynamically added on server side via PHP */ }
});

PHP-Seite:

$requestString = file_get_contents('php://input');
$myObject = json_decode($requestString); // same object as was sent in the ajax call
$myObject->id = 30; // This will dynamicaly add the id property to the myObject object

ODER SENDEN SIE NUR EIN DUMMY-EIGENTUM aus Javascript, das Sie in PHP ausfüllen werden.

Adrian Cumpanasu
quelle
Ich denke, das Senden einer Dummy-Eigenschaft von JS und das Ausfüllen auf der PHP-Seite ist die einfachste intelligentere Lösung. Vielen Dank!
Adrian P.
8
o_O O_o o_O O_o
theflowersoftime