I'm using following function to import the csv file into db. All is working fine. But I'm also want its also insert $_SESSION['userid'] with CSV file. please help me. thanks
function csv_file_to_mysql_table($source_file, $target_table, $max_line_length=10000) {
if (($handle = fopen("$source_file", "r")) !== FALSE) {
$columns = fgetcsv($handle, $max_line_length, ",");
foreach ($columns as &$column) {
$column = str_replace(".","",$column);
}
$insert_query_prefix = "INSERT INTO $target_table (".join(",",$columns).")\nVALUES";
while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
while (count($data)<count($columns))
array_push($data, NULL);
$query = "$insert_query_prefix (".join(",",quote_all_array($data)).");";
mysql_query($query);
}
fclose($handle);
}
}
function quote_all_array($values) {
foreach ($values as $key=>$value)
if (is_array($value))
$values[$key] = quote_all_array($value);
else
$values[$key] = quote_all($value);
return $values;
}
function quote_all($value) {
if (is_null($value))
return "NULL";
$value = "'" . mysql_real_escape_string($value) . "'";
return $value;
}
csv_file_to_mysql_table($uploadfile,"import_csv");
echo "file is imported successfully!";
}
I imagine something like this would work. Just append the extra field after you do your array joins.
I don't know what your user_id column is called, i just assumed user_id
$insert_query_prefix = "INSERT INTO $target_table (".join(",",$columns).",user_id)\nVALUES";
add the user_id value to the values argument
$query = "$insert_query_prefix (".join(",",quote_all_array($data)).",".$_SESSION['userid'].");";
Look for "ADD HERE"... just tack the column name in after you get them and also add the data to the end of your array once its built... should be simple as that.
foreach ($columns as &$column) {
$column = str_replace(".","",$column);
}
//ADD HERE
$columns[] = "userid";
$insert_query_prefix = "INSERT INTO $target_table (".join(",",$columns).")\nVALUES";
while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
while (count($data)<count($columns))
array_push($data, NULL);
//ADD HERE
$data[] = $_SESSION['userid']
$query = "$insert_query_prefix (".join(",",quote_all_array($data)).");";
mysql_query($query);
Related
I have a php code that I connect to an oracle database and with a request to retrieve the information I want, here is my code :
$query = "SELECT ACTIVE_SIZES FROM ADA_ACTIVE_SIZE2_VIEW WHERE ADA_STYLE = 'SCPCL4'";
$result = odbc_exec($connect, $query);
while($final = odbc_fetch_array($result)) {
print_r($final); //Array ( [ACTIVE_SIZES] => XS-S-M-L-XL-2XL )
}
Now I'm reading a csv file and I would like to adapt this code to add the results of my queries in a column at the end of the file. I already add two columns at the end of this one, but my query doesn't return anything in the csv file, how can I do please?
<?php
//Modifications on csv file
$delimiter = ";";
$csv_data = array();
if (($handle = fopen($nomcsv, 'r')) !== FALSE) {
while (($data = fgetcsv($handle, 10000, $delimiter)) !== FALSE) {
//Add two columns at the end
$data['Pictures Names'] = (!empty($data[4]) ? ($data[7] ?: '') . "_" . $data[4] . '.jpg' : '');
$data['Color-Description'] = (!empty($data[3]) ? (ltrim($data[4], '0') ?: '') . "-" . $data[3] : '');
//Query
$query = "SELECT ACTIVE_SIZES FROM ADA_ACTIVE_SIZE2_VIEW WHERE ADA_STYLE = '".$data[4]."'";
$result = odbc_exec($connect, $query);
while($final = odbc_fetch_array($result)) {
$data['Sizes'] = $final;
var_dump($final); //array(1) { ["ACTIVE_SIZES"]=> string(8) "XS-S-M-L" }array(1) { ["ACTIVE_SIZES"]=> string(8) "XS-S-M-L" }...
}
$csv_data[] = $data;
var_dump($csv_data); //["Pictures Names"]=> string(15) "SCJEG4_1041.jpg" ["Color-Description"]=> string(12) "1041-MUSTARD" ["Sizes"]=> array(1) { ["ACTIVE_SIZES"]=> string(15) "XS-S-M-L-XL-2XL" } } }
}
fclose($handle);
}
if (($handle = fopen($nomcsv, 'w')) !== FALSE) {
foreach ($csv_data as $data) {
fputcsv($handle, $data, $delimiter);
}
fclose($handle);
}
?>
At the end I have this in my csv file:
Try this, only thing is you need to define your ActiveSizes index and push it to the sizes index
$delimiter = ";";
$csv_data = array();
if (($handle = fopen($nomcsv, 'r')) !== FALSE) {
while (($data = fgetcsv($handle, 10000, $delimiter)) !== FALSE) {
//Add two columns at the end
$data['Pictures Names'] = (!empty($data[4]) ? ($data[7] ?: '') . "_" . $data[4] . '.jpg' : '');
$data['Color-Description'] = (!empty($data[3]) ? (ltrim($data[4], '0') ?: '') . "-" . $data[3] : '');
//Query
$query = "SELECT ACTIVE_SIZES FROM ADA_ACTIVE_SIZE2_VIEW WHERE ADA_STYLE = '".$data[4]."'";
$result = odbc_exec($connect, $query);
while($row = odbc_fetch_array($result)) {
$data['Sizes'][] = $row['ACTIVE_SIZES'];
}
$csv_data[] = $data;
}
fclose($handle);
}
//var_dump($csv_data);
if (($handle = fopen($nomcsv, 'w')) !== FALSE) {
foreach ($csv_data as $data) {
fputcsv($handle, $data, $delimiter);
}
fclose($handle);
}
I have a CSV defined like the data this.
"PID", "FName", "LName", "Email"
2425751712402934017,
1037862, "Jason", "Van Hooser", "jvanhooser#example.com"
961741, "Alana", "Traxler", "atraxler#example.com"
1100854, "Emily", "Walcheck", "ewalcheck#example.com"
1166892, "Mary", "Thomas", "mthomas#example.com"
8853065679823467777,
1179079, "Donna", "Thimm", "dthimm#example.com"
927671, "Lillian", "Wasson", "lwasson#example.com"
1175139, "Barry", "Tollison", "btollison#example.com"
1058086, "Christina", "Viktorin", "cviktorin#example.com"
What I need to do is iterate through it and when it comes to the lines where there is only the PID field with the long number, I need to store that in a variable ($wkey) and then use it in an insert statement. I know we could put the value on each row but the process that outputs the file cannot do that.
Hwere is my code:
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if($flag) {
$flag = false;
continue;
}
$import = "INSERT into exp_wb_bulk_reg(`WKey`,`PID`,`FName`,`LName`, `Email`,`status`) "
. "values($wkey, '$data[0]','$data[1]','$data[2]','$data[3]','I')";
// Use the sql to insert into the table
}
fclose($handle);
How would I modify this to do what I need?
Here's working code:
// skip header line
$data = fgetcsv($handle, 1000, ",");
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
// get wkey for lines that has empty second column
if(trim($data[1]) == "") {
$wkey = $data[0];
}
if(trim($data[1]) != "") {
$import = "INSERT into exp_wb_bulk_registrations(`WebinarKey`, `PID`,`FName`,`LName`, `Email`,`status`) "
. "values($wkey, '$data[0]','$data[1]','$data[2]','$data[3]','I')";
echo $import."<br />";
}
}
fclose($handle);
You could just check the size of $data array. Something like:
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if(count($data) == 4){
$import = "INSERT into exp_wb_bulk_reg(`WKey`,`PID`,`FName`,`LName`, `Email`,`status`) "
. "values($wkey, '$data[0]','$data[1]','$data[2]','$data[3]','I')";
// Use the sql to insert into the table
} else if(count($data) == ?) {
//DO STUFF
}
}
fclose($handle);
Here's my variant:
$wkey = ''; // just for sure
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
if(count($data)==1) { // hey, we found a wKey! let's remember it
$wkey = $data[0]; continue;
}
$import = "INSERT into exp_wb_bulk_reg(`WKey`,`PID`,`FName`,`LName`, `Email`,`status`) "
. "values($wkey, '$data[0]','$data[1]','$data[2]','$data[3]','I')";
}
fclose($handle);
I am wondering whether it is possible to read a specific value from CSV specifed the row number and column number.
Lets say I want to read data from row number 44 and column number K?
I dont want to parse through the complete CSV. How to read specific data?
Hope I am clear with my question? Any answer would be appreciated.
CSV files have no index, so you would need at least to go to the 44th line and retrieve it:
$file = new SplFileObject($path);
$file->setFlags(SplFileObject::READ_CSV);
$single = new LimitIterator($file, $offset = 43, $limit = 1);
list($row) = iterator_to_array($single, false);
$k = 10;
echo $row[$k];
Here is a function that accepts the path to a CSV file, and inserts all records to the given MySQL table, paying attention to the column names:
<?php
function csv_file_to_mysql_table($source_file, $target_table, $max_line_length=10000) {
if (($handle = fopen("$source_file", "r")) !== FALSE) {
$columns = fgetcsv($handle, $max_line_length, ",");
foreach ($columns as &$column) {
$column = str_replace(".","",$column);
}
$insert_query_prefix = "INSERT INTO $target_table (".join(",",$columns).")\nVALUES";
while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
while (count($data)<count($columns))
array_push($data, NULL);
$query = "$insert_query_prefix (".join(",",quote_all_array($data)).");";
mysql_query($query);
}
fclose($handle);
}
}
function quote_all_array($values) {
foreach ($values as $key=>$value)
if (is_array($value))
$values[$key] = quote_all_array($value);
else
$values[$key] = quote_all($value);
return $values;
}
function quote_all($value) {
if (is_null($value))
return "NULL";
$value = "'" . mysql_real_escape_string($value) . "'";
return $value;
}
?>
I am using the following function to import csv files to mysql:
function csv_2_mysql($source_file, $target_table, $max_line_length=10000) {
if (($handle = fopen("$source_file", "r")) !== FALSE) {
$columns = fgetcsv($handle, $max_line_length, ",");
foreach ($columns as &$column) {
$column = preg_replace('/[^a-z0-9]/i', '', $column);
}
$insert_query_prefix = "INSERT INTO $target_table (".join(",",$columns).")\nVALUES";
while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
while (count($data)<count($columns))
array_push($data, NULL);
$query = "$insert_query_prefix (".join(",",quote_all_array($data)).");";
mysql_query($query);
}
fclose($handle);
}
}
function quote_all_array($values) {
foreach ($values as $key=>$value)
if (is_array($value))
$values[$key] = quote_all_array($value);
else
$values[$key] = quote_all($value);
return $values;
}
function quote_all($value) {
if (is_null($value))
return "NULL";
$value = "'" . mysql_real_escape_string($value) . "'";
return $value;
}
The problem is, that sometimes the headers are not on the first row due to cutting and merging of csv files at the source so for example it may end up looking like this:
value1,value2,value3,value4
value1,value2,value3,value4
value1,value2,value3,value4
header1,header2,header3,header4
value1,value2,value3,value4
value1,value2,value3,value4
value1,value2,value3,value4
value1,value2,value3,value4
header1,header2,header3,header4
value1,value2,value3,value4
value1,value2,value3,value4
value1,value2,value3,value4
value1 is unique so I know that there is never a duplicate row except for headers. How can I adjust the function so that the duplicate header rows are removed if they exist and to ensure that the remaining header row is used for $columns? I would just set the column values manually except each csv may have a different number of columns (except header1 and value1 which are always present as it is a unique timestamp).
UPDATE:
Well, I figured it out but it feels wrong using both fopen and file_get_contents. Will I run into problems with this on large csv's?
function csv_2_mysql($source_file, $target_table, $uid, $nid, $max_line_length=10000) {
if (($handle = fopen("$source_file", "r")) !== FALSE) {
$handle2 = file_get_contents($source_file) or exit;
$handle_row = explode("\n", $handle2);
foreach ($handle_row as $key => $val) {
$row_array = explode(',', $val);
foreach ($row_array as $key => $val) {
$row_array[$key] = trim(str_replace('"', '', $val));
}
if(!in_array('header1', $row_array)) {
unset ($row_array);
}
else {
$columns = $row_array;
}
}
foreach ($columns as &$column) {
$column = preg_replace('/[^a-z0-9]/i', '', $column);
}
$insert_query_prefix = "INSERT INTO $target_table (".join(",",$columns).")\nVALUES";
while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
while (count($data)<count($columns))
array_push($data, NULL);
$query = "$insert_query_prefix (".join(",",quote_all_array($data)).");";
mysql_query($query);
}
fclose($handle);
}
}
function quote_all_array($values) {
foreach ($values as $key=>$value)
if (is_array($value))
$values[$key] = quote_all_array($value);
else
$values[$key] = quote_all($value);
return $values;
}
function quote_all($value) {
if (is_null($value))
return "NULL";
$value = "'" . mysql_real_escape_string($value) . "'";
return $value;
}
I guess you could have an array to push the value of the first column (since you say it is unique) and check it for duplicates. If it is a duplicate ignore the line and continue.
if (($handle = fopen($source_file, "r")) !== FALSE) {
$columns = fgetcsv($handle, $max_line_length, ",");
foreach ($columns as &$column) {
$column = str_replace(".","",$column);
}
while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
while(count($data) < count($columns)) {
array_push($data, NULL);
}
$c = count($data);
for($i = 0; $i < $c; $i++) {
$data[$i] = "'{$data[$i]}'";
}
$sql[] = '(' . implode(',', $data) . ", '" . $_POST['custgroup'] . "'," . $_POST['user_id'] . ')';
}
$db = new PDO("mysql:host=localhost;dbname=test;","root","");
$insert = $db->prepare("INSERT INTO $target_table (". implode(',', $columns) .',custgroup,user_id) VALUES ' .implode(',', $sql));
$insert->execute();
I have a script like this which will insert csv data into database according to header,and 2 extra datas which is group and user id. It works well , but when my name in csv file is
Sher's Aria then it will have error.I know it's because of the symbol single quote in the name, ' , so what can I do to solve this problem so that any name with single quote can be inserted as well?
Thank you.
Edit:
function csv_file_to_mysql_table($source_file, $target_table, $max_line_length=10000) {
if($source_file != '')
{
if (($handle = fopen($source_file, "r")) !== FALSE) {
$columns = fgetcsv($handle, $max_line_length, ",");
$esc_columns = array();
foreach ($columns as &$column) {
$column = str_replace(".","",$column);
$esc_columns[] = escapeSqlName($column);
}
$esc_columns[] = escapeSqlName('custgroup');
$esc_columns[] = escapeSqlName('user_id');
$sqlsmttempl = 'INSERT INTO %s (%s) VALUES (%s)';
$sqlsmt = sprintf($sqlstmttempl,
escapeSqlName($target_table),
implode(',', $esc_columns),
implode(',',array_fill(0, count($esc_columns), '?')) // the parameter placeholders
);
$db = new PDO("mysql:host=localhost;dbname=test;","root","");
$insert = $db->prepare($sqlsmt);
while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
while(count($data) < count($columns)) {
$data[] = NULL;
}
$data[] = $_POST['custgroup'];
$data[] = $_POST['user_id'];
if($insert->execute($data))
{
header("Location:customer-search.php");
}
else
{
echo "no";
}
}
fclose($handle);
}
}
if (isset($_POST['submit'])) {
$file = $_FILES['filename']['tmp_name'];
$table = 'UserAddedRecord';
csv_file_to_mysql_table($file,$table);
}
You are already using PDO, so you should make PDO handle your escaping for you
with your prepared statement. The code below does that.
Note that you still have a possible security issue because you assign table
and column names dynamically. The code below attempts to make sure that won't
result in any SQL injections, but you should still be cautious.
But you won't have any problems with unescaped input to the VALUES() part,
and the insertions should be much faster since you prepare the statement
only once.
function escapeSqlName($name, $quotechar='`') {
// This is to escape column names. This $quotechar ONLY WORKS WITH MYSQL
// ANSI syntax is to use $quotechar='"' and double them where-ever " is in the table name.
return $quotechar.str_replace($quotechar, $quotechar.$quotechar, $name).$quotechar;
}
if (($handle = fopen($source_file, "r")) !== FALSE) {
$columns = fgetcsv($handle, $max_line_length, ",");
$esc_columns = array();
foreach ($columns as &$column) {
$column = str_replace(".","",$column);
$esc_columns[] = escapeSqlName($column);
}
// your two extra columns
$esc_columns[] = escapeSqlName('custgroup');
$esc_columns[] = escapeSqlName('user_id');
$sqlsmttempl = 'INSERT INTO %s (%s) VALUES (%s)';
$sqlsmt = sprintf($sqlsmttempl,
escapeSqlName($target_table), // the escaped table name
implode(',', $esc_columns), // the escaped column names
implode(',',array_fill(0, count($esc_columns), '?')) // the parameter placeholders
);
// $sqlsmt should now look like 'INSERT INTO `thetable` (`col1`,`col2`,...) VALUES (?,?,...)';
$db = new PDO("mysql:host=localhost;dbname=test;","root","");
$insert = $db->prepare($sqlsmt); // prepare statement ONCE, execute with new values MULTIPLE TIMES
while (($data = fgetcsv($handle, $max_line_length, ",")) !== FALSE) {
while(count($data) < count($columns)) {
$data[] = NULL;
}
// your two extra values
$data[] = $_POST['custgroup'];
$data[] = $_POST['user_id'];
$insert->execute($data); // does data escaping for you.
}
}
One benefit (or maybe even purpose) of prepared statments is the separation of the actual statement and its parameters (the paylod data).
Instead of building a string that contains the paylod data you should bind those parameters via PDOStatement::bindParam or PDOStatement::bindValue.
CSV escaping
Surround your fields with quotes to contain the apostrophes in a CSV file. For example in your CSV:
"title", "name"
"Mr", "O'Hara"
Database escaping
You should look at escaping your data using PDO as #VolkerK suggests.
Use
mysql_real_escape_string
for each entry in the csv file before inserting the value in the array.
so, replace
$data[$i] = "'{$data[$i]}'";
with
$data[$i] = "'".mysql_real_escape_string($data[$i])."'";