This has to be simple, but I can't seem to find an answer....
I have a generic stdClass object $foo
with no properties. I want to add a new property $bar
to it that's not already defined. If I do this:
$foo = new StdClass();
$foo->bar = '1234';
PHP in strict mode complains.
What is the proper way (outside of the class declaration) to add a property to an already instantiated object?
NOTE: I want the solution to work with the generic PHP object of type stdClass.
A little background on this issue. I'm decoding a json string which is an array of json objects. json_decode()
generates an array of StdClass object. I need to manipulate these objects and add a property to each one.
Do it like this:
$foo = new stdClass();
$foo->{"bar"} = '1234';
now try:
echo $foo->bar; // should display 1234
I always use this way:
$foo = (object)null; //create an empty object
$foo->bar = "12345";
echo $foo->bar; //12345
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
)
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.
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 want to edit the decoded JSON, try getting it as an associative array instead of an array of objects.
$data = json_decode($json, TRUE);
Source: Stackoverflow.com