When doing stdClass in PHP we can do it this way:
// Create new stdClass Object
$init = new stdClass;
// Add some test data
$init->foo = "Test data";
$init->bar = new stdClass;
$init->bar->baaz = "Testing";
$init->bar->fooz = new stdClass;
$init->bar->fooz->baz = "Testing again";
$init->foox = "Just test";
Is there any other alternative way to do with so that it looks cleaner like we can do with JavaScript?
Thanks.
$array = array('x'=>123);
$object = (object) $array;
Related
I need to clone an object, then remove some properties from the clone. Using unset() on the cloned object works fine, but not on the cloned objects array of objects. I have simplified the object as it has quite a few more properties but the premise is the same.
$testobject = new stdClass();
$testobject->propertya = 'banana';
$testobject->propertyb = 'orange';
$testobject->propertyc = 'apple';
$testobject->childarray = array();
$testobject->childarray[] = new stdClass();
$testobject->childarray[0]->childpropertya = 'cola';
$testobject->childarray[0]->childpropertyb = 'bread';
$testobject->childarray[0]->childpropertyc = 'pasta';
echo "Original object:\n";
print_r($testobject);
$cloneobject = clone $testobject;
unset($cloneobject->propertyb);
foreach ($cloneobject->childarray as $index => $data) {
unset ($data->childpropertya);
}
unset($cloneobject->childarray['childpropertyc']);
echo "Original object expected to be the same but is NOT!:\n";
print_r($testobject);
I expect the $testobject not to change, but it does. Why?!
I have re-created the format in a 3v4l here
Solved, thanks for the tip #nice_dev
$testobject = new stdClass();
$testobject->propertya = 'banana';
$testobject->propertyb = 'orange';
$testobject->propertyc = 'apple';
$testobject->childarray = array();
$testobject->childarray[] = new stdClass();
$testobject->childarray[0]->childpropertya = 'cola';
$testobject->childarray[0]->childpropertyb = 'bread';
$testobject->childarray[0]->childpropertyc = 'pasta';
echo "Original object \n";
print_r($testobject);
$cloneobject = unserialize(serialize($testobject));
unset($cloneobject->propertyb);
foreach ($cloneobject->childarray as $index => $data) {
unset ($data->childpropertya);
}
unset($cloneobject->childarray['childpropertyc']);
echo "Original object is the same!\n";
print_r($testobject);
echo "Copied object is now different than $testobject!\n";
print_r($cloneobject);
The problem is simple:
I have an object like
{a:'A', b:'B'}
and i want it to be like
{a:'A', new_a:'A', b:'B', new_b:'B'}
The code used is:
<?php
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
foreach($obj as $field=>$value)
{
$obj->{'new_'.$field} = $value;
}
The output is:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 21290 bytes) in /path/to on line 9
Line 9 is this:
$obj->{'new_'.$field} = $value
I do have alternatives to solve the problem, but i don't understand why this particular code generates this error.
Does anybody know the reason for this error, eventually an explanation.
Thank you!
The problem is, as you're iterating the source object properties, you're adding more properties to the source object, so the foreach loop can never end.
You can see this happening by adding a var_dump call to the loop:
foreach ($obj as $field => $value)
{
$obj->{'new_'.$field} = $value;
var_dump($obj);
}
Results in:
object(stdClass)#1 (29) {
["a"]=>
string(1) "A"
["b"]=>
string(1) "B"
["new_a"]=>
string(1) "A"
["new_b"]=>
string(1) "B"
["new_new_a"]=>
string(1) "A"
["new_new_b"]=>
string(1) "B"
["new_new_new_a"]=>
...
Instead, create a new object and replace the old one:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$newObj = new stdClass();
// Copy old properties
foreach ($obj as $field => $value) {
$newObj->{$field} = $value;
}
// Create new properties
foreach($obj as $field => $value) {
$newObj->{'new_' . $field} = $value;
}
Or even:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$newObj = new stdClass();
// Copy old properties and create new
foreach ($obj as $field => $value) {
$newObj->{$field} = $value;
$newObj->{'new_' . $field} = $value;
}
I'm not sure why there are so many suggestions to create a second object to work around this. In my opinion, the simplest thing to do would just be to grab the fields before the loop with get_object_vars, so that you're only iterating over the initial fieldset:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$fields = get_object_vars($obj);
foreach ($fields as $field => $value) {
$obj->{'new_'.$field} = $value;
}
See https://eval.in/937616
You are appending more data unto the same object you are Looping through, using also the properties of the same Object.... To counter that, you can just do something like this:
<?php
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$obj2 = clone $obj;
foreach($obj as $field=>$value)
{
$key = 'new_'.$field;
$obj2->{$key} = $value;
}
// IF YOU STILL WISH TO HAVE $obj AS YOUR MAIN OBJECT,
// YOU CAN AS WELL RE-CLONE $obj2 INTO $obj AND DELETE $obj2 LIKE SO:
$obj = $obj2;
unset($obj2);
var_dump($obj);
var_dump($obj2);
UPDATE
If you wish to be consistent (ie: without Cloning) and also for reasons that #Dan has mentioned, You could simply use stdClass() like so:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$obj2 = new stdClass();
foreach($obj as $field=>$value)
{
$key = 'new_'.$field;
$obj2->{$field} = $value;
$obj2->{$key} = $value;
}
$obj = clone $obj2;
unset($obj2);
var_dump($obj);
// YIELDS:
object(stdClass)[3]
public 'a' => string 'A' (length=1)
public 'new_a' => string 'A' (length=1)
public 'b' => string 'B' (length=1)
public 'new_b' => string 'B' (length=1)
AS told you have to create another $obj
instead of using the object inside the loop
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$obj2 = new stdClass();
foreach($obj as $field=>$value)
{
$obj2->{$field} = $value;
$obj2->{'new_'.$field} = $value;
}
$obj = $obj2;
echo '<pre>';
var_dump($obj);
your code is stuck in a infinite loop because if you have:
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
foreach($obj as $field=>$value)
{
$obj->{'new_'.$field} = $value;
}
In each iteration, you add a new position into the object, and this position must be iterated by the foreach.
You can clone the original object and iterate the clone, into the iteration you can add the new position to the original object.
$obj = new stdClass();
$obj->a = 'A';
$obj->b = 'B';
$objcopy = clone $obj;
foreach($objcopy as $field=>$value)
{
$obj->{'new_'.$field} = $value;
}
I tried to change an object into array but seems like it doesn't work this way. Could someone tell me what to do in this case?
$blockedNumber = DB::select('SELECT COUNT(*) AS number FROM users_blocked WHERE (f_block = ? OR f_chat_block = ? OR f_hide_posts = ?)', array(1, 1, 1));
$number = (array) $blockedNumber;
var_dump($number[0]['number']);
var_dump shows me "Cannot use object of type stdClass as array"
From your reply, you can do this, and it will solve it.
$blockedNumber = DB::select('SELECT COUNT(*) AS number FROM users_blocked WHERE (f_block = ? OR f_chat_block = ? OR f_hide_posts = ?)', array(1, 1, 1));
$number = (array) $blockedNumber[0];
var_dump($number['number']);
Try it out.
If you need explanation let me know, I'll explain the reason. But, first check if its working.
$obj = new stdClass();
$objB = new stdClass();
$objB->deepFoo = 'bar';
$obj->bla = array(1,2,3,$objB);
$obj->blub = new stdClass();
$obj->blub->foo = 'bar';
function rekursiveObjectToArray($obj){
if(is_object($obj)){
$obj = (array)$obj;
}
if(is_array($obj)){
$obj = array_map('rekursiveObjectToArray',$obj);
}
return $obj;
}
$obj = rekursiveObjectToArray($obj);
var_dump($obj);
I need to create a JSON object using PHP, as I need to give attributes to each node like XML uses I can't just create a load of PHP arrays (I think), so I am creating PHP objects and doing that way.
The problem is I can quite get the JSON formatted properly.
This is what I am trying:
$object = new stdClass();
$object->{'0'}['title'] = 'Home';
$object->{'0'}['entry'] = '123';
$object->{'1'}['title'] = 'About';
$object->{'1'}['entry'] = '123';
$object->{'2'}['title'] = 'Gallery';
$object->{'2'}['entry'] = '123';
$object->{'2'} = new stdClass();
$object->{'2'}->{'0'}['title'] = 'Past';
$object->{'2'}->{'0'}['entry'] = '1234';
$object->{'2'}->{'1'}['title'] = 'Present';
$object->{'2'}->{'1'}['entry'] = '1235';
$object->{'2'}->{'0'} = new stdClass();
$object->{'2'}->{'0'}->{'0'}['title'] = '1989';
$object->{'2'}->{'0'}->{'0'}['entry'] = '12345';
$object->{'2'}->{'0'}->{'1'}['title'] = '1990';
$object->{'2'}->{'0'}->{'1'}['entry'] = '12346';
$ob=json_encode($object);
echo $ob;
Which outputs:
{
"0":{"title":"Home","entry":"123"},
"1":{"title":"About","entry":"123"},
"2":{
"0":{
"0":{"title":"1989","entry":"12345"},
"1":{"title":"1990","entry":"12346"}},
"1":{"title":"Present","entry":"1235"}
}
}
I need "2" of the first node to have attributes "title":"Gallery","entry":"123" but also contain the sub nodes for Past and Present, with the same again for the years.
In XML it may look something like this:
<0 title="Home" entry="123">
<0/>
<1 title="About" entry="123">
<1/>
<2 title="Gallery" entry="123">
<0 title="Past" entry="1234">
<0 title="1989" entry="12345"><0/>
<1 title="1990" entry="12346"><1/>
<0/>
<1 title="Present" entry="1235">
<1/>
<2/>
The easiest way to use json with PHP is to use the built in json_encode() and json_decode() functions.
This is really nice because you can encode php arrays straight into json without having to do anything!
$array = array(
array(
"title" => "Home",
"entry" => "123"
),
array(
"title" => "About",
"entry" => "123"
),
array(
"title" => "Gallery",
"entry" => "123",
),
);
And continue to nest as such, you can then convert that into a json object:
$json = json_encode($array);
With an output like:
[{"title":"Home","entry":"123"},{"title":"About","entry":"123"},{"title":"Gallery","entry":"123"}]
You can then access these again with php by doing a json_decode and moving around it like an object.
I made a playground for you to mess with here:
http://codepad.viper-7.com/qzMJO3
Hope that helps!
you're deleting them with your object creation:
swap these lines around:
$object->{'2'}['title'] = 'Gallery';
$object->{'2'}['entry'] = '123';
//this line creating the new object is effectively erasing the previous 2 lines.
$object->{'2'} = new stdClass();
to become:
$object->{'2'} = new stdClass();
$object->{'2'}['title'] = 'Gallery';
$object->{'2'}['entry'] = '123';
You're setting $object->{'2'} and $object->{'2'}->{'0'} with new stdClass(), loosing the data you've set previously.
Try this:
<?php
$object = new stdClass();
$object->{'0'}['title'] = 'Home';
$object->{'0'}['entry'] = '123';
$object->{'1'}['title'] = 'About';
$object->{'1'}['entry'] = '123';
$object->{'2'}['title'] = 'Gallery';
$object->{'2'}['entry'] = '123';
$object->{'2'}['0']['title'] = 'Past';
$object->{'2'}['0']['entry'] = '1234';
$object->{'2'}['1']['title'] = 'Present';
$object->{'2'}['1']['entry'] = '1235';
$object->{'2'}['0']['0']['title'] = '1989';
$object->{'2'}['0']['0']['entry'] = '12345';
$object->{'2'}['0']['1']['title'] = '1990';
$object->{'2'}['0']['1']['entry'] = '12346';
$ob=json_encode($object);
When creating a object in php used to return JSON is it possible to add a property and force it to go at the top? I'd like this since the object is exposed via an API and it is nice to have ids at the top.
For example:
$obj = new stdClass();
$obj->name = 'John';
$obj->age = 26;
$obj->id = 3645;
When you json_encode() this, it turns into:
{
"name": "John",
"age": 26,
"id": 3645
}
Is there a way to force id at the top of the object even though it is added last? Note, I can't simply just add id before adding name and age because of other dependent code.
It's easily possible if you use an associative array instead of an object, i.e.
$x = ['name' => 'john', 'age' => 26]; // or: $x = (array)$obj
$x = ['id' => 123] + $x;
echo json_encode($x);
// {"id":123,"name":"john","age":26}
However, it's important to note that in JSON property ordering is not defined and should not be relied upon. If what you currently have works, this change would be rather useless in fact.
Not very elegant but...
$obj = new stdClass();
$obj->name = 'John';
$obj->age = 26;
$obj->id = 3645;
$name = $obj->name;
$age = $obj->age;
unset($obj->name);
unset($obj->age);
$obj->name = $name;
$obj->age = $age;
echo json_encode($obj);
Hmm, nice question!
It is not possible to add a property and force it to go at the top.
You have to sort the object properties or the array keys.
Some nitpicking here: JSON is unordered by definition, but the browsers respect the insertion order. More: https://code.google.com/p/v8/issues/detail?id=164
JSON
4.3.3 Object An object is a member of the type Object. It is an unordered collection of properties each of which contains a
primitive value, object, or function. A function stored in a property
of an object is called a method.
Check this out: http://ideone.com/Hb4rGQ
<?php
function array_reorder_keys($array, $keynames){
if(empty($array) || !is_array($array) || empty($keynames)) return;
if(!is_array($keynames)) $keynames = explode(',',$keynames);
if(!empty($keynames)) $keynames = array_reverse($keynames);
foreach($keynames as $n){
if(array_key_exists($n, $array)){
$newarray = array($n=>$array[$n]); //copy the node before unsetting
unset($array[$n]); //remove the node
$array = $newarray + array_filter($array); //combine copy with filtered array
}
}
return $array;
}
$obj = new stdClass();
$obj->name = 'John';
$obj->age = 26;
$obj->id = 3645;
function get_json_sorted($object, $array) {
return json_encode(array_reorder_keys(get_object_vars($object), $array));
}
var_dump(get_json_sorted($obj, array('id', 'name', 'age')));
This is a solution. Turn the object into an assoc array. Get the last item (both key and value) off of the array (I'm assuming id is the last element) and move it to the front. Finally convert the assoc array back into an object.
$data_array = json_decode(json_encode($obj), true);
if(is_array($data_array)) {
end($data_array);
$data_array = array_merge(array(key($data_array) => array_pop($data_array)), $data_array);
$data = json_decode(json_encode($data_array), false);
}
This is a similar answer to Jacks' answer ( https://stackoverflow.com/a/24900322/6312186 ) but that caused a fatal error for me. I had to tweak it a bit by casting to array, using array_merge() and cast back to object, but this worked nicely for me:
$obj = (object) array_merge( (array)$obj2, (array)$obj);
This code is more generic and should work for all versions of PHP, including strict mode. Full code here
$obj = new stdClass(); // create new object
$obj->name = 'john';
$obj->age = '26';
$obj2 = new stdClass(); // we want to add this object to the top of $obj
$obj2->id = 'uid2039';
$obj = (object) array_merge( (array)$obj2, (array)$obj);
var_dump($obj);
// object(stdClass)#8700 (3) { ["id"]=> string(7) "uid2039" ["name"]=> string(4) "john" ["age"]=> string(2) "26" }
If you are json_encodeing this, you don't need to cast it back to an object again before encoding it:
$arr = ['name' => 'John', 'age' => '26'];
echo json_encode($arr);
// {"name":"john","age":"26"}
// is the same as:
$obj = (object)$arr;
echo json_encode($obj );
// {"name":"john","age":"26"}