loop for part of a multidimensional array - php

I've done a multistep form in PHP storing the data in a multidimensional array (I've created an array inside $_SESSION array and named it $_SESSION['inserimento'])
then i have $_SESSION['inserimento']['name'],$_SESSION['inserimento']['city']...
I would like to apply the strtolower() function to all the values before adding them to mysql
I've tried this code but it doesn't work
foreach ($_SESSION['inserimento'] as $k=>$v){
$v=strtolower($v);
}
I think I'm misunderstanding how to make a loop on multidimensional array.

Use array_map() to apply a function to all elements in an array:
$_SESSION['inserimento'] = array_map('strtolower', $_SESSION['inserimento']);
Or a regular foreach loop (inside the loop $v is a copy, so you need to affect to the original array):
foreach ($_SESSION['inserimento'] as $k => $v) {
$_SESSION['inserimento'][$k] = strtolower($v);
}
Or a foreach loop with reference ($v is no longer a copy, it is a reference to the original element):
foreach ($_SESSION['inserimento'] as &$v) {
$v = strtolower($v);
}
unset($v); // remember to unset, or $v will still be a reference to the last element after the loop

Use:
foreach ($_SESSION['inserimento'] as $k => $v) {
$_SESSION['inserimento'][$k] = strtolower($v);
}
This is happening because $v is a copy of the value inside the iteration, not a reference to the variable that contains the value.

You need to have a variable defined outside of the foreach loop.
$lowerValue = '';
foreach ($_SESSION['inserimento'] as $k => $v) {
$lowerValue = strtolower($v);
}

Try using array_walk
array_walk($_SESSION['inserimento'], function(&$value, $key) {
$value = strtolower($value);
});
The & before $value indicates that the variable is passed by reference.

Related

Should I unset both `$key` and `$value` after every foreach statement?

All the answers I've found only talk about unsetting $value except one, which wasn't clear to me. So here I am. Say I have the line:
foreach ($data as $key => $value)
{
// do stuff
}
Should I put these two lines after?
unset($key);
unset($value);
Or can I omit unset($key)? Also, is it recommended to ALWAYS use unset after every foreach? Say I have nested foreach loops, like this:
foreach ($data as $key => $value)
{
foreach ($data[$key] as $key => $value)
{
// do stuff
}
unset($key);
unset($value);
}
unset($key);
unset($value);
Would the nested unset() functions interfere with the highest level foreach? In other words, are the nested $key and $value the same as the highest level $key and $value?
The solution to your problem is easier than you think it is.
Simply change the variable names for your nested loop, like so:
foreach ($data as $key => $value) {
foreach ($value as $subkey => $subvalue) {
// do stuff
}
}
With the above code, you can access the array data from $date[$key] (Which is actually equal to $value inside the parent loop) as $subkey and $subvalue respectively.
You can also still access the parent loop data anywhere inside the parent foreach loop with $key and $value respectively.

php foreach with arrays and objects and redefining their value

I'm trying to foreach through an array of objects inside an array. I'm not receiving errors, but it seems not to be storing the new value I'm trying to establish. I've found many answers on here closely related to this question, but I'm not understanding, and I'm hoping someone can make this clearer.
Essentially, this converts kg to lbs.
$kg_conv = 2.20462262;
$weights = array($data['progress']->weight, $data['progress']->squats,
$data['progress']->bench, $data['progress']->deadlift);
foreach ($weights as $value) {
$value = $value * $kg_conv;
}
The values in the array come out unchanged. From what I've read, I should be using $data['progress'] and iterating through that, but I'm not understanding how to refer to only some of the elements inside instead of all of them. I also tried cutting out some redundancy by storing the objects in $progress instead of $data['progress'] but still not success.
UPDATE: The following has not worked
1
foreach ($weights as &$value) {
$value = $value * $kg_conv;
}
2
foreach ($weights as $key => &$value) {
$value = $value * $kg_conv;
}
3
foreach ($weights as $key => $value) {
$weights[$key] = $value * $kg_conv;
}
it does not work because you do not modify data array, you only modify copy made from this array, which is another array in memory
Solution: (will work for object's fields too)
$kg_conv = 2.20462262;
$weights = ['weight', 'squats','bench', 'deadlift'];
foreach ($data['progress'] as $key=>&$value) {
if ( in_array($key,$weights)
$value = $value * $kg_conv;
}
$value contains only a copy of the array element.
You can pass the object by reference like this:
foreach ($weights as &$value) {
$value = $value * $kg_conv;
}
Note the & before $value.
See References Explained in the php documentation or What's the difference between passing by reference vs. passing by value? here on stackoverflow.
Edit 2:
But note that this will only change the values in the $weights array, not your object stored in $data['progress'], as it's value has been copied into $weights. To achieve this, you can reference the object properties when constructing the data array in the following way (this step was commented out in my testcase code) :
$weights = array(&$data['progress']->weight, &$data['progress']->squats,
&$data['progress']->bench, &$data['progress']->deadlift);
Note the & operator again.
But probably the solution of maxpower is cleaner for your requirement.
Edit:
After your comment I created the following test case which works fine:
<?php
class foo {
public $test = 5;
public $test2 = 10;
}
$obj = new foo();
$obj2 = new foo();
$obj2->test = 3;
$data = array('progress' => $obj, 'p2' => $obj2);
// this copies the values into the new array
$weights = array($data['progress']->test, $data['progress']->test2);
// this makes a reference to the values, the original object will be modified
// $weights = array(&$data['progress']->test, &$data['progress']->test2);
var_dump($weights);
$kg_conv = 2.20462262;
foreach ($weights as &$value) {
$value = $value * $kg_conv;
}
var_dump($weights);
The result is:
array(2) {
[0]=>
int(5)
[1]=>
int(10)
}
array(2) {
[0]=>
float(11.0231131)
[1]=>
&float(22.0462262)
}
The PHP foreach manual describes this topic in great detail. To summarise why you are not seeing the results you expect, here is a short explanation.
Imagine you have an array $arr = ['one', 'two', 'three']. When you execute a foreach loop on this array, PHP will internally create a copy of your array:
foreach ($arr as $key => $value) {
$value = 'something'; // You are modifying the copy, not the original!
}
To modify the original array, you have two options.
Use the $key variable to access the element at given key in the original array:
$arr[$key] = 'something'; // Will change the original array
Tell PHP to use a reference to the original element in $value:
foreach ($arr as $key => &$value) {
$value = 'something'; // $value is reference, it WILL change items in $arr
}
Both approaches are valid; however, the second is more memory-efficient because PHP does not have to copy your array when you loop through it - it simply references the original.
In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference. In your example code should look like this:
foreach ($weights as &$value) {
$value = $value * $kg_conv;
}
But referencing $value is only possible if the iterated array can be referenced (i.e. if it is a variable).
You can also use indexes to acces array value directly. This code works pretty fine too:
foreach ($weights as $key => $value) {
$weights[$key] = $value * $kg_conv;
}
More here: http://php.net/manual/en/control-structures.foreach.php

PHP Array reference, modifying array values

I'm trying to modify an array when looping through it and increment certain values.
$data = ['traits' => [[['amt' => 1]]]];
var_dump($data['traits']);
foreach ($data['traits'] as $key => &$index) {
foreach ($index as $key => &$value) {
$value['amt'] = $value['amt']++; // This should increment
if (in_array($key, $input)) {
$i++;
$insert["field_".$i] = $key."_1";
}
}
}
var_dump($data['traits']); // SAME AS PREVIOUS VAR_DUMP
What you are doing in the loop is undefined:
$value['amt'] = $value['amt']++;
The outcome of that depends on what's evaluated first. In this case $value['amt']++ seems to be evaluated first and then assigned to $value['amt'] again; the side effect of the increment is lost.
On the other hand, the following statement will work as expected:
$value['amt']++;

how do you call a function inside a foreach statement

I am trying to use foreach statment to run through a function that preg_replaces using regular expression. Can someone help, because my method doesn't work..
$reg_sent is an array
function reg_sent($i){
$reg_sent = "/[^A-Za-z0-9.,\n\r ]/";
return preg_replace($reg_sent, '', $i);
}
foreach($reg_sent as $key=>$value){
$value = reg_sent($value);
}
Check array_map.
$reg_sent = array_map("reg_sent", $reg_sent);
This will call reg_sent on every cell of the array, and return a new array with values modified. You can replace the foreach block you stated, with the above.
You're not getting any affect because the foreach loop needs to access the elements by reference:
foreach($reg_sent as $key => &$value)
{
$value = reg_sent($value);
}
Note that I added the & in the loop before $value. Otherwise, foreach operates on a copy of the value, and when that is modified within the loop, you will never see that value outside of the loop.
You need to pass your variable by reference:
foreach($reg_sent as $key=>&$value){
Otherwise you are operating on a local copy that only keeps its value in the loop.
function reg_sent($i){
$reg_sent = "/[^A-Za-z0-9.,\n\r ]/";
return preg_replace($reg_sent, '', $i);
}
foreach($reg_sent as $key => &$value){
$value = reg_sent($value);
}
unset($value);
var_dump($reg_sent);

Using foreach effectively in PHP

So I don't think I'm making full use of the foreach loop. Here is how I understand foreach.
It goes like foreach(arrayyouwanttoloopthrough as onevalueofthatarray)
No counter or incrementing required, it automatically pulls an array, value by value each loop, and for that loop it calls the value whatever is after the "as".
Stops once it's done with the array.
Should basically replace "for", as long as dealing with an array.
So something I try to do a lot with foreach is modify the array values in the looping array. But in the end I keep finding I have to use a for loop for that type of thing.
So lets say that I have an array (thing1, thing2, thing3, thing4) and I wanted to change it....lets say to all "BLAH", with a number at the end, I'd do
$counter = 0;
foreach($array as $changeval){
$counter++;
$changeval = "BLAH".$counter;
}
I would think that would change it because $changeval should be whatever value it's at for the array, right? But it doesn't. The only way I could find to do that in a] foreach is to set a counter (like above), and use the array with the index of counter. But to do that I'd have to set the counter outside the loop, and it's not even always reliable. For that I'd think it would be better to use a for loop instead of foreach.
So why would you use foreach over for? I think I'm missing something here because foreach has GOT to be able to change values...
Thanks
OH HEY One more thing. Are variables set in loops (like i, or key) accessible outside the loop? If I have 2 foreach loops like
foreach(thing as value)
would I have to make the second one
foreach(thing2 as value2) ]
or else it would have some problems?
You can use a reference variable instead:
foreach ($array as &$value)
{
$value = "foo";
}
Now the array is full of foo (note the & before $value).
Normally, the loop variable simply contains a copy of the corresponding array element, but the & (ampersand) tells PHP to make it a reference to the actual array element, rather than just a copy; hence you can modify it.
However, as #Tadeck says below, you should be careful in this case to destroy the reference after the loop has finished, since $value will still point to the final element in the array (so it's possible to accidentally modify it). Do this with unset:
unset($value);
The other option would be to use the $key => $value syntax:
foreach ($array as $key => $value)
{
$array[$key] = "foo";
}
To answer your second question: yes, they are subsequently accessible outside the loop, which is why it's good practice to use unset when using reference loop variables as in my first example. However, there's no need to use new variable names in subsequent loops, since the old ones will just be overwritten (with no unwanted consequences).
You want to pass by reference:
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value)
{
$value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
The extended foreach syntax is like this:
foreach ($array as $key => $value) {
}
Using the $key, you can index the original array:
foreach ($array as $key => $value) {
$array[$key] = "BLAH";
}
Incrementing from 0 to ...
foreach($array as $changeval){
if (!isset($counter)) { $counter = 0; }
$counter++;
$changeval = "BLAH".$counter;
}
Using the index/key of the ARRAY
foreach($array as $key => $changeval){
$changeval = "BLAH".$key;
}
You can use the key when looping with foreach:
foreach ($array as $key => $value)
{
$array[$key] = "foo";
}
But note that using a reference like Will suggested will be faster for such a case - but anyway, the $key => $value-syntax is quite useful sometimes.

Categories