I am working on a CSV file upload function. The whole script is working fine and the way I am doing it is by eliminating the first line of the CSV file which is the heading and then using the data only to insert into the database. However, this adds a restriction for the CSV to be sorted always. I need to accept unsorted CSV too. For example, if a column name is in second column and of the CSV file then the array index becomes $arr[1]. Currently, I am using $arr[1] for inserting the values in the database and performing operations. This is bad. If the user uploads an unsorted CSV where name is in 4th column and say phone is in 2nd column where earlier I expected the name to be, then this will disrupt the whole operation. Therefore, how can I use the first heading line and use them as a key like $arr['name'] for performing the required operations?
My current code:
$csvFile = fopen($_FILES['file']['tmp_name'], 'r');
fgetcsv($csvFile);
$arr = [];
while($data = fgetcsv($csvFile, 100, ",")){
$arr['id'] = $data[0]; // WANT TO USE $data['id'] FROM CSV FILE's FIRST LINE
$arr['date'] = date('Y-m-d', strtotime($data[1])); // WANT TO USE $data['date'] FROM CSV FILE's FIRST LINE
$arr['stock'] = $data[2]; // WANT TO USE $data['stock'] FROM CSV FILE's FIRST LINE
$arr['price'] = $data[3]; // WANT TO USE $data['price'] FROM CSV FILE's FIRST LINE
$ar[] = $arr;
}
fclose($csvFile);
How can I get the keys from the file and use it here in the code above?
UPDATE
I see that if I store the keys in array and print it like this
$csvFile = fopen($_FILES['file']['tmp_name'], 'r');
$getFileKeys = fgetcsv($csvFile); // STORED KEYS IN ARRAY
fgetcsv($csvFile);
print_r($getFileKeys);
then I get an array like this:
Array
(
[0] => id
[1] => date
[2] => stock_name
[3] => price
)
I need to write logic in such a way that if I have 4 variables one for each of the element above, then no matter if the index changes for any element, the variable will receive the same value dynamically.
Since you already got the keys inside $getFileKeys variable you can simply use a for loop to loop through the array of keys and dynamically assign the indexes based upon the field.
$getFileKeys = fgetcsv($csvFile);
$keys = [];
for($i = 0; $i < count($getFileKeys); $i++){
if($getFileKeys[$i] == 'id'){
$keys['id'] = $i;
}else if($getFileKeys[$i] == 'date'){
$keys['date'] = $i;
}else if($getFileKeys[$i] == 'stock_name'){
$keys['stock'] = $i;
}else if($getFileKeys[$i] == 'price'){
$keys['price'] = $i;
}
}
while($getData = fgetcsv($csvFile, 100, ",")){
$arr['id'] = $getData[$keys['id']];
$arr['date'] = date('Y-m-d', strtotime($getData[$keys['date']]));
$arr['stock'] = trim($getData[$keys['stock']]);
$arr['price'] = $getData[$keys['price']];
$ar[] = $arr;
}
The $keys array now dynamically stores the indexes for each key. Therefore, this now sorts the CSV file no matter at what order which column is placed in.
You could make variables out of the first line, so that you can call them by her name.
$exampleLine=[
'id' => 1
'date' => '2022-07-01'
'stock_name' => 'stock_name'
'3' => 'price'
];
foreach($exampleLine as $name){
$$name=$name;
}
This will give you the variables with appropriate content, so that $id contains 1, $date '2022-07-01' and so on.
to prevent different spellings, you could still use lcfirst and trim.
PHP-Manual
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.
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);
I have 2 array's with the same length. array $gPositionStudents and array $gPositionInternships. Each student is assigned to a different internship, That part works.
Now I want the first element (index 0) of $gPositionStudent refer to the second (index 1) element of array $gPositionInternship. That implicitly means that the last element of $gPositionStudents refer to the first element of $gPositionInternship. (I included a picture of my explanation).
My Code is:
// Make table
$header = array();
$header[] = array('data' => 'UGentID');
$header[] = array('data' => 'Internships');
// this big array will contains all rows
// global variables.
global $gStartPositionStudents;
global $gStartPositionInternships;
//var_dump($gStartPositionInternships);
$rows = array();
$i = 0;
foreach($gStartPositionStudents as $value) {
foreach($gStartPositionInternships as $value2) {
// each loop will add a row here.
$row = array();
// build the row
$row[] = array('data' => $value[0]['value']);
//if($value[0] != 0 || $value[0] == 0) {
$row[] = array('data' => $gStartPositionInternships[$i]);
}
$i++;
// add the row to the "big row data (contains all rows)
$rows[] = array('data' => $row);
}
$output = theme('table', $header, $rows);
return $output;
Now I want that I can choose how many times, we can shift. 1 shift or 2 or more shifts. What I want exists in PHP?
Something like this:
//get the array keys for the interns and students...
$intern_keys = array_keys($gStartPositionInternships);
$student_keys = array_keys($gStartPositionStudents);
//drop the last intern key off the end and pin it to the front.
array_unshift($intern_keys, array_pop($intern_keys));
//create a mapping array to join the two arrays together.
$student_to_intern_mapping = array();
foreach($student_keys as $key=>$value) {
$student_to_intern_mapping[$value] = $intern_keys[$key];
}
You'll need to modify it to suit the rest of your code, but hopefully this will demonstrate a technique you could use. Note the key line here is the one which does array_unshift() with array_pop(). The comment in the code should explain what it's doing.
I think you want to do array_slice($gPositionsStudents, 0, X) where X is the number of moves to shift. This slices of a number of array elements. Then do array_merge($gPositionsStudents, $arrayOfSlicedOfPositions); to append these to the end of the original array.
Then you can do an array_combine to create one array with key=>value pairs from both arrays.
I need to get a count of the first column's values. These ID's might or might not exist in any given .csv file I receive. So I need to loop through the .csv file looking at the first column and either adding it to a holding array ($PWSs) if it doesn't exist or incrementing the count in this holding array if I've already added it.
I have the first loop using fgetcsv()..this works for cracking into the file:
$PWSs = array();
$handle2 = fopen ($uploadfileandpath,"r");
while ($field2array = fgetcsv ($handle2, 130000, ","))
{
// Here is where I would add value or increment $PWSs array
while (?)
{
if ($field2array[0] != ?)
{
// Add or increment
}
}
}
Here is actual data. The first column has IDs for Public Water Systems. I need to count them.
"00513","08/13/2009","090834311A","R","4","OR1000x6","N","N","E",,1,".73","COLILERT"
"00513","08/13/2009","090834312A","R","39","OR1000x6","N","N","E",,1,".35","COLILERT"
"00154","08/13/2009","090835401A","R","300 Falls Road","OR100016","N","N","E",,1,".10","COLILERT"
"95343","08/13/2009","090835601A","R","Room 1 Sink","OR1000x6","N","N","E",,1,,"COLILERT"
"94585","08/14/2009","090837701A","R","Kitchen","OR1000x6","N","N","E",,1,,"COLILERT"
"94704","08/14/2009","090837801A","R","Outside Tap","OR1000x6","N","N","E",,1,,"COLILERT"
"01430","08/14/2009","090838201A","R","100 Deer Park Ln OT","OR1000x6","N","N","E",,1,,"COLILERT"
"00625","08/14/2009","090839001A","R","Dano and N Rose","OR100016","N","N","E",,1,".35","COLILERT"
"00405","08/17/2009","090840301A","R","Westmont Drive","OR100016","N","N","E",,1,".28","COLILERT"
"01031","08/17/2009","090840401A","R","Unit 2 Faucet","OR100016","N","N","E",,1,,"COLILERT"
"00625","08/17/2009","090840601A","R","Luman Road","OR1000x6","N","N","E",,1,".35","COLILERT"
"00513","08/17/2009","090841001A","R","40","OR1000x6","N","N","E",,1,".18","COLILERT"
"00513","08/17/2009","090841002A","R","10","OR1000x6","N","N","E",,1,".16","COLILERT"
$fh = fopen('file.csv', 'rb');
$PWS = array();
while($row = fgetcsv($fh)) {
$PWS[$row[0]]++;
}
Basically it'll populate the PWS using the first column values as keys, and increment them as they come along. Afterwards, given your sample csv above, you'd end up with
$PWS = array(
'00513' => 4
'00154' => 1
'95343' => 1
'94585' => 1
etc...
);
function get_pws()
{
$PWSs = array();
$handle2 = fopen ($uploadfileandpath,"r");
while ($field2array = fgetcsv ($handle2, 130000, ","))
{
if(!in_array($field2array[0], $PWSs))
{
array_push($PWSs, array('key'=>$field2array[0], 'count'=>1));
}
else
{
foreach($PWSs as &$PWS)
{
if($PWS['key'] == $field2array[0])
{
++$PWS['count'];
}
}
}
}
return $PWSs;
}
I haven't actually run and tested this script, so hopefully it works and it's what you're looking for ;)
Edit: Thanks for pointing that out dq. Again, I haven't tested it (not on a machine with PHP installed atm), so hopefully it still works (if it worked in the first place) :P
You only need one while loop. Your outer while loop will stop when it hits the eof, because fgetcsv() will return FALSE.
Then just test for the column to be NULL or "" an empty string. If the column did not exist in the given array, you should use isset() to make sure it exists first in your conditional.