Foreach loop takes last value only - php

I am new in PHP and I have little problem. I have code like this:
$file = $_FILES['sel_file']['name'];
$chk_ext = explode(".",$file);
if(strtolower($chk_ext[1]) == "txt")
{
$filename = $_FILES['sel_file']['tmp_name'];
$handle = fopen($filename, "r");
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
$array = array( $data[0]);
foreach( $array as $value )
{
$number=$value;
}
$obj=new Sender("$number");
}
header("location:bulk.php?msg=send");
}
else
{
header("location:bulk.php?invalid=file");
exit();
}
$obj->Submit ();
Problem is that only last value comes out from text file in $obj=new Sender("$number");, please help me out.

fgetcsv() already return an array so: $array = array( $data[0]); just means that you only retrieve the first element of the array of fields which is $data.
In the foreach loop you should just replace the $array variable with $data.
The loop woould then look like this:
foreach( $data as $value )
{
$number=$value;
}
$obj=new Sender("$number");
means that for every element in $data, you hold it inside $number, loops again and put it again in $number overwriting it.
After the foreach loop the value of $number would be the last field of the row.
You should just put the line $obj=new Sender("$number"); inside the loop, so that every element of every row would be put in Sender.

No surprise. You loop over all the values, continually overwriting $number with the most recently retrieved value. When the loop exits, you end up with only the last one.
Probably you want something more like:
foreach($array as $value) {
$obj = new Sender($value);
}
your code also makes very little sense. You take an uploaded file, presumably CSV, read a line from it, extract the FIRSt value from that line. force the value into an array, then read back that ONE value in the array (the ONLY value in the array), and do something with it.
Even if your foreach wasn't overwriting the value, you still only have one single value to loop on anyways.

You are overwriting the contents of number each iteration. You can instead make number an array which stores each value at incrementing elements.
foreach( $array as $value )
{
$number[]=$value;
}
$obj=new Sender($number);

That's because you assign a new value to $number in each iteration. Either you need to append to that variable ($number .= $value) or you need to add it to an array ($number[] = $value).

Related

Unset array element and reseting array values in PHP

So I have 2 files. In file 1 I have a table and there I randomly select some fields and store (store in session) them in an array of 2D arrays. When I click on the cell I send this data to my file 2 where I want to check if I clicked on a randomly selected array or not and if I did, I want to remove this 2D array from an main array.
But as soon as I click on one of the selected arrays, the array crashes.
File 1 PHP stuff immportant for this:
session_start();
$_SESSION['arrays'] = $stack ;
File 2 PHP:
session_start();
if (isset($_SESSION['arrays'])) {
$stack = $_SESSION['arrays'];
for ($i = 0; $i< count($stack);$i++){
if($cooridnates == $stack[$i]){
unset($stack[$i]);
array_values($stack);
$i--;
$Result = true;
break;
}
}
$_SESSION['arrays'] = $stack ;
I am suspecting the error might be in 2 things:
count($stack) used, but I don't believe this is the main reason.
The way I store session.
I have tried using manuals from W3Schools and official PHP website and also SOF, but with no use.
But still, I am not sure if the array_values() and unset() is working correctly since the thing chrashes and I can't test it correctly.
I would appreciate any tips.
You need to assign the result of array_values($stack); back to the $stack variable.
$stack = array_values($stack);
There's also no need to use $i-- when you do this, since you're breaking out of the loop after you find a match.
Instead of a loop, you can use array_search():
$pos = array_search($coordinates, $stack);
if ($pos !=== false) {
unset $stack[$pos];
$Result = true;
$stack = array_values($stack);
$_SESSION['arrays'] = $stack;
}
you can do this like that by using foreach loop:
session_start();
if (!empty($_SESSION['arrays'])) {
foreach( $_SESSION['arrays'] as $key => $val){
if($cooridnates == $val){
unset($_SESSION['arrays'][$key]); // if you want this removed value then assign it a variable before unsetting the array
$Result = true;
break;
}
}
}

Php function returns the same with different parameters

There is a csv file with data about the weather. I am making something which calculates the mean of a column per station from that csv file. That column is passed in the parameters of the function.
First of all I have this list of id's from the weatherstation. The values I add to the list are arrays which contains the sum and count of a datatype.
$station_id = array("960350", "960870", "961090", "961790", "962210", "962370", "962950", "963230",
"965810", "966330", "966850", "967430", "967470", "967490", "967810",
"968050", "968810", "969330", "969350", "969870", "970140", "970480",
"970720", "971200", "971260", "971460", "971800", "971925", "972300",
"972400", "972600", "973000", "973400", "974280", "974300", "975600",
"977240", "977900", "978100", "979000");
//Every item in the array becomes a key, with an array as a value.
//StationID => [sum, count]
$station_id = array_fill_keys($station_id, []);
The function down here reads the lines of the csv file, adds the value if it is there, adds one to the counter, calculates the mean and prints it per station. Finally it clears the values of the array station_id.
function calc_average($to_be_calc){
global $station_id; //array with station_id's as keys. The value is the sum and the count. (0=sum , 1+count)
global $file; //The csv file.
while (($line = fgetcsv($file)) !== FALSE) {
list($STN, $DATE, $TIME, $TEMP, $DEWP, $STP, $SLP, $VISIB, $WDSP, $PRCP, $SNDP, $FRSHTT, $CLDC, $WNDDIR) = $line;
if (is_numeric($STN)) {
$station_id[$STN][0] += $$to_be_calc; //Sums the values of for example temp
$station_id[$STN][1] += 1; //Adds one to the counter of the station.
}
}
foreach ($station_id as $key => $value) {
if ($value[1] > 0) {
//Calculate average
$average = number_format($value[0] / $value[1], 1, ',', ' ');
//print average per station
echo "Average of station $key: $average</br>";
}
}
foreach ($station_id as $key => $value){
unset($key);
}
}
The problem I have now is that when I call it like this:
calc_average("TEMP");
echo "<br>";
calc_average("CLDC");
It prints the averages of the temperature per station twice. Instead of first TEMP, then CLDC. Like this. If I first call calc_average with CLDC as parameter it only does with CLDC.
I have no idea how this is possible. Therefore, my question is how to fix this.
SOLUTION
I didn't rewind the pointer at the end of my function. All I had to do was add rewind($file); to my function. I works great now. Thanks
Placing my answer from the comments in an actual answer:
I am assuming $file is a file pointer obtained using something like fopen(). If so, are you resetting the pointer back to the beginning of the file? If not, $line = fgetcsv($file) will always return false at the start of the second calc_average() call.

Fill array with contents of csv with php

I am trying to fill a array with a csv so each field is separate part of the array, when i have filled the array and echo it out it quite literally says array for every enter.
I have a feeling that once i sort the csvfull array that the sku might need to be in loop inside the main processing loop to.
$ocuk = fopen("ocuk.csv", "r");
while (($result = fgetcsv($ocuk)) !== false)
{
$csvfull[] = $result;
}
print_r ($csvfull[0][1]);
$sku="$csvfull[1]";
while (($csv = fgetcsv($ocuk)) !== FALSE)
{
if (false === empty(array_intersect($sku, $csv)))
{
code to display the results from csv that match the $sku variable
}
}
What i need it to do is csvfull array to fill with the contents of the csv such i can then call it into the variable sku to do comparison in next part of the code.
EDIT example of what i mean
csv example
data,data2,data3,data4 etc
data10,data20,data30,data40 etc
the array would then be like this
$csvfull=array() would contain the below
array("data","data2","data3","data4");
array("data10","data20","data30","data40");
then when i call csvfull[1] it display data2 then would go onto data 20 etc
$csvfull is a 2-dimensional array. The first dimension is the rows of the CSV, the second dimension is the columns. So $csvfull[1] is an array containing all the values from the second line of the file. To get the SKU, you need to drill down to the appropriate column, e.g.
foreach ($csvfull as $row) {
$sku = $row[1];
// Do something with $sku
}
If you want to get an array of all the SKUs, you can do:
$sku = array();
foreach ($csvfull as $row) {
$sku[] = $row[1];
}
try like this:
<?php
$ocuk = fopen('clientes.csv','r');
$i=0;
while(!feof($ocuk)){
$values = fgetcsv($ocuk);
if(empty($values[1] )){ // any index which is not empty to make sure that you are reading valid row.
continue;}
$csvfull[$i] = $values;
$i++;
}
print_r($csvfull);
.
fclose($ocuk);

How can I run 2 loops together in PHP without duplicating values?

I'm trying to check MD5 of some data with md5 some files, both of them are stored in one dimensional arrays. Say I have 4 files in the $files array with the same number of $datas, the following code prints "NO DIFFERENCE" 12 times instead of 4 times.
foreach($files as $file) {
foreach($datas as $data) {
if(md5($data) !== md5_file($file)) {
echo "NO DIFFERENCE";
}
}
}
How do I prevent duplicating a loop?
Update:
Both arrays $datas and $files contains equal number of values but the tricky part is the values in $files array starts from key number 2 (because I removed "." and ".." from scandir result) whereas in $datas array values start from key number 0.
the following code prints "NO DIFFERENCE" 12 times instead of 4 times.
The reason for that is you have a nested loop.
For each value in the $files array, your inner foreach will run once.
So say if you have 3 values in $files and 4 values in $datas, the loop will run as follows:
First value in $files iterated
Inner loop runs, and iterates through all 4 values in $datas
Second value in $files iterated
Inner loop runs, and iterates through all 4 values in $datas
Third value in $files iterated
Inner loop runs, and iterates through all 4 values in $datas
Try this with one loop like this :
foreach($datas as $key => $value) {
if(md5($value) !== md5_file($files[$key])) {
echo "NO DIFFERENCE";
}
}
Note: The loop work when you have same no of values for both arrays
If you want to compare md5(files) to the mfs5(datas) you can simply do this:
for ($i = 0; $i < sizeof($files); $i++){
if(md5($datas[$i]) !== md5_file($files[$i+2]))
echo "NO DIFFERENCE";
}
If you want to check if each file have one corresponding md5(datas) then you should use you double loop as you did.
First, are you sure that !== is the operator you want to use to say 'no difference' ?
If you are looking for equality, maybe you want to use ===
Second, md5(...) is time consuming, so extract the hash in a variable.
Third, if you mean equality, you can add a break in the inner loop to stop looping as soon as you find the equality.
foreach($files as $file) {
$md5File = md5_file($file); // extract in a variable
foreach($datas as $data) {
if(md5($data) === $md5File) { // === instead of !==
echo "NO DIFFERENCE";
break; // break as soon as possible
}
}
}
You could use a callback function. But then you should be clear about how exactly you will describe an algorithm of your problem.
The following sample shows how to maybe achieve it. But it assumes that the arrays are in the same order and that you don't want to cross-compare everything. Also array_udiff may not be the best approach for it.
function compare_by_md5($data, $file) {
if( md5($data) === md5_file($file)) {
echo "NO DIFFERENCE";
}
}
array_udiff($datas, $files, 'compare_by_md5');
Sample is shown here: http://codepad.org/lYOyCuXA
If you simply want to detect if there is a difference:
$dataHashes = array();
foreach($datas as $data) {
$dataHashes[md5($data)] = true;
}
$different = false;
foreach($files as $file) {
if(!isset($dataHashes[md5_file($file)])) {
$different = true;
break;
}
}
var_dump($different);
If you want to know which files are different, then:
$dataHashes = array();
foreach($datas as $data) {
$dataHashes[md5($data)] = true;
}
foreach($files as $file) {
if(!isset($dataHashes[md5_file($file)])) {
echo $file, 'is different', PHP_EOL;
}
}

PHP Go to the next element of array

I have created an array list with the following code:
<?php
$ids = array();
if (mysql_num_rows($query1))
{
while ($result = mysql_fetch_assoc($query1))
{
$ids["{$result['user_id']}"] = $result;
}
}
mysql_free_result($query1);
?>
Now, i need to read two elements from the array. The first is the current and the second one is the next element of array. So, the simplified process is the following:
i=0: current_element (pos:0), next_element (pos:1)
i=1: current_element (pos:1), next_element (pos:2)
etc
To do this, i have already written the following code, but i cant get the next element for each loop!
Here is the code:
if (count($ids))
{
foreach ($ids AS $id => $data)
{
$userA=$data['user_id'];
$userB=next($data['user_id']);
}
}
The message i receive is: Warning: next() expects parameter 1 to be array, string given in array.php on line X
Does anyone can help? Maybe i try to do it wrongly.
The current, next, prev, end functions work with the array itself and place a position mark on the array. If you want to use the next function, perhaps this is the code:
if (is_array($ids))
{
while(next($ids) !== FALSE) // make sure you still got a next element
{
prev($ids); // move flag back because invoking 'next()' above moved the flag forward
$userA = current($ids); // store the current element
next($ids); // move flag to next element
$userB = current($ids); // store the current element
echo(' userA='.$userA['user_id']);
echo('; userB='.$userB['user_id']);
echo("<br/>");
}
}
You'll get this text on the screen:
userA=1; userB=2
userA=2; userB=3
userA=3; userB=4
userA=4; userB=5
userA=5; userB=6
userA=6; userB=7
userA=7; userB=8
You get the first item, then loop over the rest and at the end of each loop you move the current item as the next first item ... the code should explain it better:
if (false !== ($userA = current($ids))) {
while (false !== ($userB = next($ids))) {
// do stuff with $userA['user_id'] and $userB['user_id']
$userA = $userB;
}
}
Previous answer
You can chunk the arrays into pairs:
foreach (array_chunk($ids, 2) as $pair) {
$userA = $pair[0]['user_id']
$userB = $pair[1]['user_id']; // may not exist if $ids size is uneven
}
See also: array_chunk()

Categories