Як додати властивість до об’єкта в PHP> = 5,3 строгий режим без генерування помилок


82

Це має бути просто, але я, здається, не можу знайти відповіді ....

У мене є загальний об’єкт stdClass $fooбез властивостей. Я хочу додати $barдо нього ще не визначену властивість . Якщо я зроблю це:

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

PHP у суворому режимі скаржиться.

Який правильний спосіб (за межами оголошення класу) додати властивість до вже створеного об’єкта?

ПРИМІТКА: Я хочу, щоб рішення працювало із загальним об'єктом PHP типу stdClass.

Трохи довідки з цього питання. Я декодую рядок json, який є масивом об'єктів json. json_decode()генерує масив об'єкта StdClass. Мені потрібно маніпулювати цими об’єктами та додати властивість до кожного.


Спробуйте передати TRUEяк 2-й параметр до json_decode. Це дасть вам асоціативний масив замість масиву об’єктів.
Racket Hazmat

1
PHP у суворому режимі на це не скаржиться. 3v4l.org/kn0hi
hakre

3
Я не знаю, чому це було закрито, оскільки це цілком слушне питання. Зараз у мене точно подібне запитання.
Стівен

Відповіді:


131

Якщо вам абсолютно потрібно додати властивість до об'єкта, я вважаю, що ви можете передати його як масив, додати своє властивість (як новий ключ масиву), а потім повернути його як об'єкт. Єдиний раз, коли ти стикаєшся з stdClassоб’єктами (я вважаю), це коли ти кидаєш масив як об’єкт або коли створюєш новий stdClassоб’єкт з нуля (і звичайно, коли тиjson_decode() щось робиш - безглуздо, що я забув!).

Замість:

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

Ви зробите:

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

Або якщо у вас вже був існуючий об’єкт stdClass:

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

Також як 1 лайнер:

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

1
Одне місце, з яким ви стикаєтеся зі StdClass, - це декодування json, що є досить поширеним явищем.
Рей

1
@Ray Я кручу головою з сумом, що не думав згадувати про це. =)
Crontab

3
Твоє рішення працює, але мені боляче на серці :) Сподівався на якийсь кричущий роздум кунг-фу або щось інше ... Зберігатиму питання ще трохи відкритим і сподіватися на якусь маловідому магію PHP.
Рей

1
@Ray hehehe ... Я хотів би, щоб у мене було щось більш елегантне для тебе. До речі, явно встановлюючи error_reporting(E_STRICT);на PHP 5.3.15-1~dotdeb.0 with Suhosin-Patch, я не отримую ніяких помилок або повідомлень при спробі встановити неіснуючу власність на об'єкт StdClass. Яку версію PHP ви використовуєте?
Crontab

Ха, майже через три роки, і я чомусь отримую негативний голос без пояснення. Дякую.
Кронтаб,

112

Зробіть це так:

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

зараз спробуйте:

echo $foo->bar; // should display 1234

2
Працює як шарм. Це має бути прийнятим рішенням.
Тарракіс

Як додати властивість до поля на об’єкті, використовуючи цей синтаксис?
Великі гроші

Помилка "Спроба присвоїти властивість не-об'єкта" у Laravel
Rejaul

навіть рядок "bar" може містити змінну: $ foo -> {$ any_variable} = '1234';
Салар

Це остаточно має бути прийнятою відповіддю, оскільки вона зберігає цілісні посилання на об’єкт (що в моєму випадку було вирішальним).
Йохан Фредрік Варен

11

Якщо ви хочете відредагувати декодований JSON, спробуйте отримати його як асоціативний масив замість масиву об'єктів.

$data = json_decode($json, TRUE);

2

Я завжди використовую такий спосіб:

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

echo $foo->bar; //12345

1

слід використовувати магічні методи __Set та __get. Простий приклад:

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

}

Звичайно, не використовуйте цей приклад як такий: взагалі ніякої безпеки :)

РЕДАГУВАТИ: бачив ваші коментарі, тут може бути альтернатива на основі роздумів та декоратора:

 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: Я не тестував свій код, лише загальна ідея ...


3
Бенджамін, я хочу використовувати загальний клас об'єктів PHP: StdClass. Я не можу змінити цей клас.
Рей

Рей, я оновив свою відповідь рішенням, яке відповідає твоїм потребам, але воно важке: - /
Бенджамін Дюбуа

1

Я не знаю, чи це нова версія php, але це працює. Я використовую 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();

Це результат. Метод збереження фактично отримує нову властивість

    Person Object
    (
       [name] => Ganga
       [age] => 23
    )

Я провів кілька тестів для коду у версіях php, і результат показує, що він працює лише для php 5 і вище. будь-яка версія нижче php5 видає помилку.
Велике дерево,

-6

Так, можна динамічно додавати властивості до об'єкта PHP.

Це корисно, коли частковий об'єкт отримується з javascript.

Сторона 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 */ }
});

Сторінка 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

АБО ПРОСТО ВІДПРАВИТЕ ФУНКЦІЙНИЙ ВЛАСНИК із javascript, який ви заповните в PHP.


Я думаю, що надсилання фіктивного властивості від JS та заповнення на стороні PHP є найпростішим розумним рішенням. Дякую!
Адріан П.

8
o_O O_o o_O O_o
theflowersoftime
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.