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);
Related
$session_activity_category = array();
foreach($search_venue as $venue_b) {
$session_activity_category[] = $this->users_model->search_categories_by_session($venue_b->activity_venue_id);
}
return $this->output
->set_content_type('application/json')
->set_status_header(200)
->set_output(json_encode(array('activity_category'=>$session_activity_category,'activity'=>$session_activity,'activity_session'=>$search_session,'activity_venue'=>$search_venue),JSON_UNESCAPED_SLASHES)
);
I want to remove the arrays given in the arrow lines
Convert the JSON to the array. Then just create a new array with the same key active category (in my example, something):
<?php
$json = '
{"something": [[
{
"blah": "blah"
},
{
"blah": "blah"
}
]]}
';
$array = json_decode($json, true);
$array = [
"something" => $array['something'][0],
];
echo json_encode($array);
Which will output:
{"something":[{"blah":"blah"},{"blah":"blah"}]}
Seems that $this->users_model->search_categories_by_session($venue_b->activity_venue_id) returns array of objects. You should parse this objects to the $session_activity_category array each iteration of search_categories_by_session function call.
$session_activity_category = array();
array_walk($search_venue, function($venue_b) use (&$session_activity_category) {
$categories = $this->users_model->search_categories_by_session($venue_b->activity_venue_id);
foreach ($categories as $category) {
$session_activity_category[] = $category;
}
});
Is it possible to set property values of an object using a foreach loop?
I mean something equivalent to:
foreach($array as $key=>$value) {
$array[$key] = get_new_value();
}
EDIT: My example code did nothing, as #YonatanNir and #gandra404 pointed out, so I changed it a little bit so it reflects what I meant
You can loop on an array containing properties names and values to set.
For instance, an object which has properties "$var1", "$var2", and "$var3", you can set them this way :
$propertiesToSet = array("var1" => "test value 1",
"var2" => "test value 2",
"var3" => "test value 3");
$myObject = new MyClass();
foreach($propertiesToSet as $property => $value) {
// same as $myObject->var1 = "test value 1";
$myObject->$property = $value;
}
Would this example help at all?
$object = new stdClass;
$object->prop1 = 1;
$object->prop2 = 2;
foreach ($object as $prop=>$value) {
$object->$prop = $object->$prop +1;
}
print_r($object);
This should output:
stdClass Object
(
[prop1] => 2
[prop2] => 3
)
Also, you can do
$object = new stdClass;
$object->prop1 = 1;
$object->prop2 = 2;
foreach ($object as $prop=>&$value) {
$value = $value + 1;
}
print_r($object);
You can implement Iterator interface and loop through the array of objects:
foreach ($objects as $object) {
$object->your_property = get_new_value();
}
Hacked away at this for a few hours and this is what i finally used. Note the parameters passed by reference in two places. One when you enter the method and the other in the foreach loop.
private function encryptIdsFromData(&$data){
if($data == null)
return;
foreach($data as &$item){
if(isset($item["id"]))
$item["id"] = $this->encrypt($item["id"]);
if(is_array($item))
$this->encryptIdsFromData($item);
}
}
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"}
Like in Java when you iterate a list, it's real easy, it's like: while(BLAH.hasNext()) { }, so how do I do that in PHP when I have an array within an stdObject that I want to iterate through each and every item?
I keep getting Catchable fatal error: Object of class stdClass could not be converted to string in /Applications/XAMPP/xamppfiles/htdocs/index.php on line 29
<?php
$apiUrl = 'https://api.quizlet.com/2.0/groups/44825?client_id=***BLOCKED FROM PUBLIC***&whitespace=1';
$curl = curl_init($apiUrl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$json = curl_exec($curl);
if ($json) {
$data = json_decode($json);
echo "<h1>Sets from \"{$data->name}\"</h1>";
foreach ($data->sets as $key => $val) {
echo "$key: $val\n";
}
echo "</ul>";
var_dump($data);
}
?>
You can/should use foreach to iterate over every element of an array.
$foo = new stdClass;
$foo->arr = array('1','7','heaven','eleven');
foreach ($foo->arr as $val)
{
if (is_object($val)) var_dump($val);
else echo $val;
}
Note the line I added to var_dump sub-objects. The error you were initially getting was that the elements of your sets array were also objects, not strings as expected. If you only need to access certain elements of the set objects, you can access them using $val->property.
For example you have an object like
$obj = new stdClass;
$obj->foo = 'bar';
$obj->arr = array('key' => 'val', ...);
$array = (array) $obj;
now you can use foreach to iterate over array.
foreach($array as $prop) {
//now if you are not sure if it's an array or not
if(is_array($prop)) {
foreach($prop as $val)
//do stuff
}
else {
//do something else
}
}
The $val variable holds another object (of type stdClass) which contains the details for an individual "set". As you can see, since it generates an error, you cannot echo a stdClass object.
You can access the values inside each object using the object->property notation that you seems to be getting familiar with. For example.
foreach ($data->sets as $set) {
echo $set->title . " by " . $set->created_by . "<br>";
}
/*
An example of the JSON object for a single $set
Access these like $set->title and $set->term_count
{
"id": 8694763,
"url": "http:\/\/quizlet.com\/8694763\/wh-test-1-2-flash-cards\/",
"title": "WH Test 1 & 2",
"created_by": "GrayA",
"term_count": 42,
"created_date": 1323821510,
"modified_date": 1323821510,
"has_images": false,
"subjects": [
"history"
],
"visibility": "public",
"editable": "groups",
}
*/
Sorry to ask, its late and I can't figure a way to do it... anyone can help?
$users = array(
array(
"name" => "John",
"age" => "20"
),
array(
"name" => "Betty",
"age" => "22"
)
);
$room = array(
"furniture" => array("table","bed","chair"),
"objects" => array("tv","radio","book","lamp"),
"users" => &$users
);
var_dump $room shows:
...
'users' => &
...
Which means "users" is a reference.
I would like to do something like this:
foreach($room as $key => $val) {
if(is_reference($val)) unset($room[$key]);
}
The main goal is to copy the array WITHOUT any references.
Is that possible?
Thank you.
You can test for references in a multi-dimensional array by making a copy of the array, and then altering and testing each entry in turn:
$roomCopy = $room;
foreach ($room as $key => $val) {
$roomCopy[$key]['_test'] = true;
if (isset($room[$key]['_test'])) {
// It's a reference
unset($room[$key]);
}
}
unset($roomCopy);
With your example data, $room['furniture'] and $roomCopy['furniture'] will be separate arrays (as $roomCopy is a copy of $room), so adding a new key to one won't affect the other. But, $room['users'] and $roomCopy['users'] will be references to the same $users array (as it's the reference that's copied, not the array), so when we add a key to $roomCopy['users'] it is visible in $room['users'].
The best I can manage is a test of two variables to determine if one is a reference to the other:
$x = "something";
$y = &$x;
$z = "something else";
function testReference(&$xVal,&$yVal) {
$temp = $xVal;
$xVal = "I am a reference";
if ($yVal == "I am a reference") { echo "is reference<br />"; } else { echo "is not reference<br />"; }
$xVal = $temp;
}
testReference($x,$y);
testReference($y,$x);
testReference($x,$z);
testReference($z,$x);
testReference($y,$z);
testReference($z,$y);
but I doubt if it's much help
Really dirty method (not well tested either):
$x = "something";
$y = &$x;
$z = "something else";
function isReference(&$xVal) {
ob_start();
debug_zval_dump(&$xVal);
$dump = ob_get_clean();
preg_match('/refcount\((\d*)\)/',$dump,$matches);
if ($matches[1] > 4) { return true; } else { return false; }
}
var_dump(isReference($x));
var_dump(isReference($y));
var_dump(isReference($z));
To use this last method in your code, you'd need to do something like:
foreach($room as $key => $val) {
if(isReference($room[$key])) unset($room[$key]);
}
because $val is never a reference as it's a copy of the original array element; and using &$val makes it always a reference
something recursive maybe.
function removeReferences($inbound)
{
foreach($inbound as $key => $context)
{
if(is_array($context))
{
$inbound[$key] = removeReferences($context)
}elseif(is_object($context) && is_reference($context))
{
unset($inbound[$key]); //Remove the entity from the array.
}
}
return $inbound;
}
function var_reference_count(&$xVal) {
$ao = is_array($xVal)||is_object($xVal);
if($ao) { $temp= $xVal; $xVal=array(); }
ob_start();
debug_zval_dump(&$xVal);
$dump = ob_get_clean();
if($ao) $xVal=$temp;
preg_match('/refcount\((\d*)\)/',$dump,$matches);
return $matches[1] - 3;
}
//-------------------------------------------------------------------------------------------
This works with HUDGE objects and arrays.
if you want to get rid of recursive elements:
<?php
$arr=(object)(NULL); $arr->a=3; $arr->b=&$arr;
//$arr=array('a'=>3, 'b'=>&$arr);
print_r($arr);
$arr_clean=eval('return '.strtr(var_export($arr, true), array('stdClass::__set_state'=>'(object)')).';');
print_r($arr_clean);
?>
output:
stdClass Object ( [a] => 3 [b] => stdClass Object *RECURSION* )
stdClass Object ( [a] => 3 [b] => )