I have a nested object that was created using json_decode and that I want to dynamically loop through in PHP and alter specific values within it. The path to the key I want to alter is stored in an indexed array that I pass to my function, where the last item in the array contains the key.
The array containing the path to the key looks like this:
array(3) {
[0]=>
string(6) "level1"
[1]=>
string(6) "level2"
[2]=>
string(6) "level3"
}
My object $obj looks like this:
{
"level1": {
"level2": {
"level3": "value"
}
}
}
When it's all objects, inside my for loop I can do this:
for($i = 0; $i < count($array); $i++) {
$obj = $obj->{$array[$i]};
if($i == count($array)-1) $obj = $value;
}
=> thus, altering the original object.
However, I'm stuck at inserting a new value into an indexed array that is part of my JSON object, using the method above. Consider that 'level3' in the following example represents an indexed array inside my object.
{
"level1": {
"level2": {
"level3": []
}
}
}
If I do:
for($i = 0; $i < count($array); $i++) {
$obj = $obj->{$array[$i]};
if($i == count($array)-1) {
if(gettype($obj) == 'object') $obj = $value;
else if(gettype($obj) == 'array') array_push($obj, $value);
}
}
When I var_dump the altered array inside the for loop, I get the expected results. However this way, the original array inside my object remains untouched. How can I achieve the array being altered in my object instead of just in local scope?
It seems that I am only able to achieve that behavior only if I access it staticly, like this: array_push($obj->level1->level2->level3, $value);
But I can't think of a dynamic way of achieving this.
I hope I made it all clear and anyone has a possible solution to this problem.
Related
Consider this array:
$super = [
"first" => ["first1","first2"],
"second" => ["second1","second2"]
];
Now let's grab a reference to the subarray:
$sub = $super["second"];
How can I reference the super array from the sub array?
I'm looking for a way to do something like this:
var_dump($sub[../"first"]);
array (size=2)
0 => string 'first1' (length=6)
1 => string 'first2' (length=6)
NO, PHP Arrays are implemented as ordered hashmaps. Which means that every key in the array gets hashed and maps directly to a value. That value could be another array, sure, but the map does not go in reverse. So a value cannot map back to a key in PHP or in the implementation of any typical hashmap. The hash only goes one way.
So in $arr = ["foo" => ["bar"]] the key "foo" in the array $arr will map to the value ["bar"], which happens to be another array. But there is no way to go in reverse order (i.e. map the value ["bar"] back to the key "foo" in $arr).
If you want this kind of co-recursive relationship, like a tree or graph, it's actually easier to accomplish with objects, because objects don't have the same by copy-by-value semantics that arrays do.
$obj = new stdClass;
$obj->first = new stdClass;
$obj->second = new stdClass;
$obj->first->parent = $obj;
$obj->second->parent = $obj;
$obj->first->value = ["first1", "first2"];
$obj->second->value= ["second1","second2"];
$first = $obj->first; // now I can ask it for its parent
$second = $first->parent->second->value;
var_dump($second);
You get
array(2) {
[0]=>
string(7) "second1"
[1]=>
string(7) "second2"
}
Now it doesn't actually matter if you change the value from $first or $obj. The object remains intact, because PHP objects aren't stored directly in the variable. They are stored in a container that's abstracted away from userland and the variable merely holds a reference to this container. So $first and $obj still both point to the same object.
So continuing from the example above, if we tried something like this ...
$second = $first->parent->second;
$first->parent->second->value = ["I changed you!", "I changed you too!"];
// This magically gets the right value
var_dump($second->value, $obj->second->value);
array(2) {
[0]=>
string(14) "I changed you!"
[1]=>
string(18) "I changed you too!"
}
array(2) {
[0]=>
string(14) "I changed you!"
[1]=>
string(18) "I changed you too!"
}
You can only know what's the parent index of an index by creating custom function like this :
function get_parent($key, $arr){
$index = 0;
foreach($arr as $keyCur => $val){
if($keyCur === $key){
$ret = [];
$ret['indexOfKey'] = $index;
$ret['valueOfKey'] = $val;
return $ret;
}
$index++;
}
return false;
}
I have a multi-query MySQLi statement that uses multiple queries and when using var_dump brings back the following:
var_dump of array:
array(1) { ["company"]=> string(8) "ffr3e456" ["high_1"]=> string(8) "8.32465" }
array(2) { ["company"]=> string(8) "gg8751hw" ["high_2"]=> string(7) "7.66574" }
The code I am using to display the array in a PHP file picks up the first array (i.e. the content of high_1 information but not the second.
code
if ($mysqli->multi_query($query)) {
do {
/* store first result set */
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_assoc()) {
for ($p=1; $p<=2; $p++)
{
echo number_format($row["high_".$p],2);
The HTML output shows the data from the first array but not the second. I am sure I am overlooking something, any advice and feedback welcomed.
$C = array_merge($A, $B);
You can read more here: http://www.php.net/manual/de/function.array-merge.php
It would be helpful if you showed the SQL statement that returns the results.
Are the returned arrays in separate $row results?
In that case you need to iterate through each $row result, something like:
foreach($query->result() as $row)
{
for ($p=1; $p<=2; $p++)
{
echo number_format($row["novhigh_".$p],2);
}
}
On a side note: It looks like the key definition inside the arrays is not logical, why not have the same key value for the "novhigh" element?
I thought I have some basic PHP skills, at least enough to do the development for simple applications, but I found myself to be stuck with very basic array operation problem.
I have results of curl operation set on $results variable. For easier code, (blame me it is too primitive.), I have used the basic loop to loop through $results variable to produce the favored results for my next operation.
$data = array();
for ($i = 0; $i < count($results); $i++) {
$row = $results[$i];
$atom->objectId = $row['objectId'];
$atom->username = $row['username'];
array_push($data, $atom);
}
var_dump(json_encode($data));
Sample data:
{
[0] => { ["objectId"]: "12345", ["username"]: "user1" },
[1] => { ["objectId"]: "12567", ["username"]: "user2" },
[2] => { ["objectId"]: "12789", ["username"]: "user3" },
[3] => { ["objectId"]: "13579", ["username"]: "user4" }
}
You can simply figure out the expected output, but the real output turned out to be:
[
{ "objectId": "13579", "username": "user4" },
{ "objectId": "13579", "username": "user4" },
{ "objectId": "13579", "username": "user4" },
{ "objectId": "13579", "username": "user4" }
]
Any idea why this is giving me ridiculous result?
Any help would be appreciated.
Thanks in advance.
What your code is doing right now:
Every loop, it is changing the properties of one object, and appending the object's reference (pass by value, but the value is the reference.) to the $data array, so you have 4 spots in the $data array pointing to only one object. Each time you loop, you change the value, the last time it is assigned is on the last value. This is why all your values are the same.
What you want to do:
Create a new object every iteration with the data and point to the new object each time.
Other solution:
If you just want an array containing the values and not a reference to an object(like your output), you could try this:
$data = array();
for ($i = 0; $i < count($results); $i++) {
$row = $results[$i];
$data[$i]['objectId'] = $row['objectId'];
$data[$i]['username'] = $row['username'];
}
var_dump(json_encode($data));
Akshay2598's answer might work out, but the explanation isn't quite right. This has nothing to do with pass-by-value or pass-by-reference: no variables are being passed.
The reason you are getting the same results is indeed related to references. When you initially create an object, the $atom variable isn't set to the object itself, but to a reference to that object, a memory address.
What you basically are doing, is changing the properties of the object $atom is pointing to, and later add that reference to that object to your array.
Because you never assign a new object to $atom, it'll keep pointing to the same object. Because it'll keep pointing to the same object, you will keep adding more references to the same object to your array.
To fix this you can simply do:
$data = array();
for ($i = 0; $i < count($results); $i++) {
$atom = new Atom(); // Add this bit to assign a new object for $atom to point to
$row = $results[$i];
$atom->objectId = $row['objectId'];
$atom->username = $row['username'];
array_push($data, $atom);
}
var_dump(json_encode($data));
I am trying to add an array to an existing array. I am able to add the array using the array_push . The only problem is that when trying to add array that contains an array keys, it adds an extra array within the existing array.
It might be best if I show to you
foreach ($fields as $f)
{
if ($f == 'Thumbnail')
{
$thumnail = array('Thumbnail' => Assets::getProductThumbnail($row['id'] );
array_push($newrow, $thumnail);
}
else
{
$newrow[$f] = $row[$f];
}
}
The fields array above is part of an array that has been dynamically fed from an SQl query it is then fed into a new array called $newrow. However, to this $newrow array, I need to add the thumbnail array fields .
Below is the output ( using var_dump) from the above code. The only problem with the code is that I don't want to create a seperate array within the arrays. I just need it to be added to the array.
array(4) { ["Product ID"]=> string(7) "1007520"
["SKU"]=> string(5) "G1505"
["Name"]=> string(22) "150mm Oval Scale Ruler"
array(1) { ["Thumbnail"]=> string(77) "thumbnails/products/5036228.jpg" } }
I would really appreciate any advice.
All you really want is:
$newrow['Thumbnail'] = Assets::getProductThumbnail($row['id']);
You can use array_merge function
$newrow = array_merge($newrow, $thumnail);
Alternatively, you can also assign it directly to $newrow:
if ($f == 'Thumbnail')
$newrow[$f] = Assets::getProductThumbnail($row['id']);
else
...
Or if you want your code to be shorter:
foreach($fields as $f)
$newrow[$f] = ($f == 'Thumbnail')? Assets::getProductThumbnail($row['id']) : $row[$f];
But if you're getting paid by number of lines in your code, don't do this, stay on your code :) j/k
for example say i have an object array called $list looks like this:
<(stdClass)#16 (3) {
["1"]=>
<(8) "50504496"
["2"]=>
<(8) "12435374"
["3"]=>
<(8) "12436374"
Im doing a foreach on the object array and removing them if they exist in the database i.e
foreach($list as $l){
//do the query
if( it exists){
//remove from objects: this is where i need help!!
}
}
i have the db logic, im just stuck to know how i can remove objects, i was thinking maybe i should create a new object and add them thier. thanks
}
Use: unset
foreach($list as $key => $obj){
if( exists .. ) {
unset($list[$key]);
}
}
run your query and if it returns >0 number of rows then you have a result, use unset($object->$var) to unset a variable
Try like:
foreach($list as $li)
{
if($li)
{
//copy into another array.
}
}
i thnk its may simple
Try like:
$i=0;
foreach($list as $li)
{
if($li)
{
$b[i] = $li;
$i++;
}
}
array '$b' will hold the values in $list which are not null