如何在 PHP > = 5.3严格模式下向对象添加属性而不产生错误

这必须很简单,但我似乎找不到答案..。

我有一个没有属性的泛型 stdClass 对象 $foo。我想添加一个新的属性 $bar到它还没有定义。如果我这样做:

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

PHP 在严格模式下抱怨。

向已实例化的对象添加属性的正确方法(在类声明之外)是什么?

注意: 我希望解决方案能够使用 stdClass 类型的通用 PHP 对象。

关于这个问题的一点背景知识。我正在解码一个 json 字符串它是一个 json 对象的数组。json_decode()生成一个 StdClass 对象数组。我需要操作这些对象并为每个对象添加一个属性。

216947 次浏览

you should use magic methods __Set and __get. Simple example:

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


}

Of course, don't use this example as this : no security at all :)

EDIT : seen your comments, here could be an alternative based on reflection and a decorator :

 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 : I didn't test my code, just the general idea...

If you absolutely have to add the property to the object, I believe you could cast it as an array, add your property (as a new array key), then cast it back as an object. The only time you run into stdClass objects (I believe) is when you cast an array as an object or when you create a new stdClass object from scratch (and of course when you json_decode() something - silly me for forgetting!).

Instead of:

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

You'd do:

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

Or if you already had an existing stdClass object:

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

Also as a 1 liner:

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

If you want to edit the decoded JSON, try getting it as an associative array instead of an array of objects.

$data = json_decode($json, TRUE);

Yes, is possible to dynamically add properties to a PHP object.

This is useful when a partial object is received from javascript.

JAVASCRIPT side:

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 side:

$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

OR JUST SEND A DUMMY PROPERTY from javascript that you will fill in PHP.

Do it like this:

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

now try:

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

I don't know whether its the newer version of php, but this works. I'm using 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();

This is the result. The save method actually gets the new property

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

This is another way:

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


echo $foo->bar; //12345