Jak dodać właściwość do obiektu w trybie ścisłym PHP> = 5.3 bez generowania błędu

82

To musi być proste, ale nie mogę znaleźć odpowiedzi ....

Mam ogólny obiekt stdClass $foobez właściwości. Chcę dodać do niego nową właściwość $bar, która nie jest jeszcze zdefiniowana. Jeśli to zrobię:

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

PHP w trybie ścisłym narzeka.

Jaki jest właściwy sposób (poza deklaracją klasy), aby dodać właściwość do już utworzonego obiektu?

UWAGA: Chcę, aby rozwiązanie działało z ogólnym obiektem PHP typu stdClass.

Trochę tła w tej kwestii. Dekoduję ciąg JSON, który jest tablicą obiektów JSON. json_decode()generuje tablicę obiektu StdClass. Muszę manipulować tymi obiektami i do każdego z nich dodać właściwość.

Promień
źródło
Spróbuj przekazać TRUEjako drugi parametr do json_decode. Otrzymasz tablicę asocjacyjną zamiast tablicy obiektów.
Rocket Hazmat
1
PHP w trybie ścisłym nie narzeka na to. 3v4l.org/kn0hi
hakre
3
Nie wiem, dlaczego to zostało zamknięte, ponieważ jest to całkowicie uzasadnione pytanie. Mam teraz dokładnie podobne pytanie.
Steven

Odpowiedzi:

131

Jeśli absolutnie musisz dodać właściwość do obiektu, uważam, że możesz rzucić ją jako tablicę, dodać swoją właściwość (jako nowy klucz tablicy), a następnie odrzucić ją z powrotem jako obiekt. Jedyny przypadek, kiedy napotkasz stdClassobiekty (jak sądzę), to rzutowanie tablicy jako obiektu lub tworzenie nowego stdClassobiektu od zera (i oczywiście, gdyjson_decode() coś - głupi, że zapomniałem!).

Zamiast:

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

Zrobiłbyś:

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

Lub jeśli masz już istniejący obiekt stdClass:

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

Również jako 1 wkładka:

$foo = (object) array_merge( (array)$foo, array( 'bar' => '1234' ) );
Crontab
źródło
1
Jednym z miejsc, które napotykasz StdClass, jest dekodowanie json, co jest dość powszechne.
Ray
1
@Ray Kręcę głową ze smutkiem, że nie pomyślałem o tym. =)
Crontab
3
Twoje rozwiązanie działa, ale rani moje serce OO :) Miałem nadzieję na jakiś rodzaj błyskotliwego refleksyjnego kung foo czy coś ... Zamierzam utrzymać to pytanie trochę dłużej i mieć nadzieję na jakąś mało znaną magię PHP.
Ray
1
@Ray hehehe ... Żałuję, że nie mam dla Ciebie czegoś bardziej eleganckiego. Nawiasem mówiąc, wyraźnie ustalone error_reporting(E_STRICT);na PHP 5.3.15-1~dotdeb.0 with Suhosin-Patch, ja nie otrzymuję żadnych błędów lub powiadomień, gdy próbuje ustawić właściwość nieistniejącego na obiekcie stdClass. Jakiej wersji PHP używasz?
Crontab
Ha, prawie trzy lata później i z jakiegoś powodu dostaję negatywną opinię. Dziękuję Ci.
Crontab
112

Zrób to tak:

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

Spróbuj teraz:

echo $foo->bar; // should display 1234
jmnerd
źródło
2
Działa jak urok. To powinno być przyjęte rozwiązanie.
Tarrakis
Jak dodać właściwość do pola w obiekcie przy użyciu tej składni?
Big Money
„Próba przypisania własności niebędącej przedmiotem” Błąd w Laravel
Rejaul
nawet ciąg „bar” może znajdować się w zmiennej: $ foo -> {$ any_variable} = '1234';
Salar
To powinno być definitywnie akceptowaną odpowiedzią, ponieważ zachowuje nienaruszone odniesienie do obiektu (co w moim przypadku było kluczowe).
Johan Fredrik Varen
11

Jeśli chcesz edytować zdekodowany JSON, spróbuj uzyskać go jako tablicę asocjacyjną zamiast tablicy obiektów.

$data = json_decode($json, TRUE);
Rocket Hazmat
źródło
2

Zawsze używam w ten sposób:

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

echo $foo->bar; //12345
Ragnar
źródło
1

powinieneś użyć magicznych metod __Set i __get. Prosty przykład:

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];
}

}

Oczywiście nie używaj tego przykładu w ten sposób: brak zabezpieczeń :)

EDYCJA: widziałem twoje komentarze, tutaj może być alternatywa oparta na refleksji i dekoratorze:

 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: Nie testowałem swojego kodu, tylko ogólny pomysł ...

Benjamin Dubois
źródło
3
Benjamin, chcę użyć ogólnej klasy obiektów PHP: StdClass. Nie mogę modyfikować tej klasy.
Ray
Ray, zaktualizowałem moją odpowiedź rozwiązaniem odpowiadającym Twoim potrzebom, ale jest ciężkie: - /
Benjamin Dubois.
1

Nie wiem, czy to nowsza wersja php, ale to działa. Używam 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();

To jest wynik. Metoda save faktycznie pobiera nową właściwość

    Person Object
    (
       [name] => Ganga
       [age] => 23
    )
Ganga
źródło
Przeprowadziłem kilka testów kodu w różnych wersjach php i wynik pokazuje, że działa tylko dla php 5 i nowszych. każda wersja poniżej php5 generuje błąd.
Big Tree
-6

Tak, możliwe jest dynamiczne dodawanie właściwości do obiektu PHP.

Jest to przydatne, gdy część obiektu jest otrzymywana z javascript.

Strona JAVASCRIPT:

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 */ }
});

Strona PHP:

$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

LUB PO PROSTU WYŚLIJ DUMMY PROPERTY z javascript, który wypełnisz w PHP.

Adrian Cumpanasu
źródło
Myślę, że wysłanie atrapy właściwości z JS i wypełnienie po stronie PHP jest najłatwiejszym i inteligentniejszym rozwiązaniem. Dzięki!
Adrian P.
8
o_O O_o o_O
O_o