Add property to stdClass at the top of the object in php - php

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"}

Related

Unsetting properties in array of objects where parent is a clone

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);

Concatenate JSON in php with read Database

I read user from the database but I return json to ajax only return the last user because I cant concatenate the json encode.
$myObj = new \stdClass();
while ($fila = $bd->fila()) {
$myObj->NOMBRE = $fila["NOMBRE"];
$myObj->ROLENAME = $fila["ROLENAME"];
$myObj->IDUSER = $fila["IDUSER"];
$myJSON = json_encode($myObj);
}
echo $myJSON;
You are now overwriting $myJson in each iteration. We can also not "concatanate" two jsons (well, we could, but we shouldn't, cause it's laborious..).
Better put everything in one array/object and json_encode() at the very end.
$myObj = new \stdClass();
$users = array(); // instantiate a new array
while ($fila = $bd->fila()) {
$myObj->NOMBRE = $fila["NOMBRE"];
$myObj->ROLENAME = $fila["ROLENAME"];
$myObj->IDUSER = $fila["IDUSER"];
// add objects to that array
$users[] = $myObj;
}
// then at the end encode the whole thing to json:
echo json_encode($users);
Now here are some variants:
If you want everything that your db is returning in this items you could shorten that to:
$users = array(); // instantiate a new array
while ($fila = $bd->fila()) {
// add the whole item (cast as Object) to that array
$users[] = (Object) $fila;
}
// then at the end encode the whole thing to json:
echo json_encode($users);
If you don't care if the items are objects or arrays you could skip the casting and just add the array to the big array:
$users[] = $fila;
Maybe if you concatenate it as array like this
$myJSON[] = $myObj;
and then after the while
echo json_encode($myJSON);
You just have to collect data to big array and then encode whole array. Also there's no reason for creating new StdObjects instead of usual arrays.
// define empty array
$result = [];
while ($fila = $bd->fila()) {
// add to the array all needed elements one by one
$result[] = [
'NOMBRE' => $fila["NOMBRE"],
'ROLENAME' => $fila["ROLENAME"],
'IDUSER' => $fila["IDUSER"],
];
}
// encode whole result
echo json_encode($result);

PHP array_merge return null in class

Why this code return null?
I check it but there is no error, And when i am call array merge with 2 default array Like ["x"=>"y","foo"=>"bar"] it work well!
See:
<?php
class ClassName
{
private $dataArray = array();
public function put($arr){
$this->dataArray = array_merge($arr,$this->dataArray);
return $this;
}
public function run(){
echo json_encode($this->dataArray);
}
}
$json = new ClassName();
$json->Test->LastLog = '123456789123456';
$json->Password = 'Mypassword';
$json->Dramatic = 'Cat';
$json->Things = array("HI" => 1, 2, 3);
$json->put($json)->run();
You Passed an object not array try like this code you got result:
$json->put((array)$json)->run();
Output is:
> {"\u0000ClassName\u0000dataArray":["Volvo XC90","BMW
> M4","MaclarenP1"],"Test":"123456789123456","Password":"Mypassword","Dramatic":"Cat","Things":{"HI":1,"0":2,"1":3},"0":"Volvo
> XC90","1":"BMW M4","2":"MaclarenP1"}
EDIT
If you want to pass the $json->Test->LastLog like this means you need to alternate you object declaration like:
$json = new ClassName();
$json->Test = array('LastLog'=>'123456789123456');
$json->Password = 'Mypassword';
$json->Dramatic = 'Cat';
$json->Things = array("HI" => 1, 2, 3);
Because in your put function is array_merge expecting array but you sent a json_object instead of array. (array) is act like json_decode...
Example: Simple Object
$object = new StdClass;
$object->foo = 1;
$object->bar = 2;
var_dump( (array) $object );
Output:
array(2) {
'foo' => int(1)
'bar' => int(2)
}

Create JSON object in PHP

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);

create stdclass with several arrays

I'm trying to create new stdclass with several arrays inside, and then to convert it to json array, for example i have this arrays:
$my_arr = array (name=>myname1, adress=>myadd1, phone=>myphone1);
$my_arr2 = array (name=>myname2, adress=>myadd2, phone=>myphone2);
And i would like to merge them to STDClass, This is what i have try:
$foo = new stdClass();
$foo->item1 = array();
foreach ($my_arr as $key => $value) {
$foo->item1[$key] = $value;
}
print_r($foo);
echo json_encode($foo);
The problem here is that i'm using only with the first array, The Result should be:
"items":[
[
{
"name":"myname1",
"adress":"myadd1",
"phone":"myphone1"
},
{
"name":"myname2",
"adress":"myadd2",
"phone":"myphone2"
},
{
"name":"myname3",
"adress":"myadd3",
"phone":"myphone3"
}
]
],
Thank you very much!
You don't need to use stdClass, just array will work well.
$foo = array('items' => array($my_arr, $my_arr2));
echo json_encode($foo);
Of course you could use stdClass also:
$foo = new stdClass();
$foo->items = array($my_arr, $my_arr2);
echo json_encode($foo);

Categories