I am creating a php script that imports a csv file into an existing mySQL database.
I am selecting the matching column headings by checking if the heading in in an array and trying to use the column number to create my input into my prepared statement.
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$numCols = count($data);
$row = array();
// process the first row to select columns for extraction
if($isFirstRow) {
$num = count($data);
for($col=0; $col<count($columns); $col++){
for($c=0; $c<$numCols; $c++)
if(!in_array($data[$c], $columns[$col])){
if($c == ($numCols-1))
{
$matchingCol[$col] = '""';
}
}
else{
$matchingCol[$col] = 'data['.$c.']';
apc_store("foo$c", $matchingCol[$col]);
}
}
$isFirstRow = false;
}
$data = array(
'contractorName' => (apc_fetch('foo1')) ,
'contractorType' => $matchingCol[3]);
$query = "INSERT INTO uploadSQL SET" . bindFields($data);
$result = $pdo->prepare($query);
$result->execute($data);
The data posted into the database is '$data[3]', '$data[5]' etc.
How can I get the INSERT to input the data stored at $data[3] and not the string '$data[3]'?
Use $data[$c] instead of 'data['.$c.']'...!?
Single quoted strings will display things almost completely "as is." Variables and most escape sequences will not be interpreted.
Not an exact solution to the problem but a work around. I'm sure there's a more efficient way.
if($isFirstRow) {
$csvRow1 = $data;
}
$num = count($data);
for($col=0; $col<count($columns); $col++){
for($c=0; $c<$numCols; $c++){
if(!in_array($csvRow1[$c], $columns[$col])){
if($c == ($numCols-1))
{
$matchingCol[$col] = '""';
}
}
else{
$matchingCol[$col] = "$data[$c]";
$c = $numCols;
}
}
}
Related
I'm wondering if I can export two deferent forms entries based on the submitter id but with a specific concept,
The concept is:
If the entry title from the first form == some entry field of the other form, let's show these two entries in the exported data in one row, and so on, something like array_map in php.
I hope that you got the idea, any help to do that?
Thanks a lot,
Magdi
Use These Codes:
(first code returns data from csv file into an array)
(second code gets data from an array and save into a csv file)
function csvExporter($path) {
$csv = array();
$row = 1;
if (($handle = fopen($path, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
$csv[str_pad($row,4,0,STR_PAD_LEFT)] = array();
for ($c = 0; $c < $num; $c++) {
$csv[str_pad($row,4,0,STR_PAD_LEFT)][$c] = $data[$c];
}
$row++;
}
fclose($handle);
}
return $csv;
}
function csvImporter($path,$array) {
$csvFile = fopen($path,'w+');
foreach ($array as $rows) {
$eachRow = '[';
foreach ($rows as $columns) {
$eachRow .= '\'' . trim($columns,'\'') .'\',';
}
$eachRow .= ']' . PHP_EOL;
}
fclose($csvFile);
}
I have a CSV file with 100 rows but want to output 5 of them at random like $data[0][1][2][3] and $data[2][2][3]
I got it to show but it shows in a group
<?php
$row = 1;
if (($handle = fopen("Book1.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
?>
Would like it to look like:
some data:<?php echo $data[0][1][2][3];?>
more data:<?php echo $data[1][1][2][3];?>
more data:<?php echo $data[5][1][2][3];?>
more data:<?php echo $data[8][1][2][3];?>
If you load the file into an array, it's easy enough to come up with a list of "random" numbers, pull the corresponding line out, and use str_getcsv the same way you used fgetcsv in your code. It isn't the most efficient way to do it, as you need to read the whole file into memory. But it's necessary to determine the number of lines before choosing your random number.
<?php
$rows = file("Book1.csv");
$len = count($rows);
$rand = [];
while (count($rand) < 5) {
$r = rand(0, $len);
if (!in_array($r, $rand)) {
$rand[] = $r;
}
}
foreach ($rand as $r) {
$csv = $rows[$r];
$data = str_getcsv($csv);
// now do whatever you want with $data, which is one random row of your CSV
echo "first column from row $r: $data[0]\n";
}
At-present I can store CSV data in to Mysql table. But my problem is, In my csv file some columns (Manufaturer, ecu group) data has duplication's. I need to remove duplicate data. How can I do this?
<?php
require_once 'db1.php';
$current_row = 1;
$handle = fopen("files/import.csv", "r");
while ( ($data = fgetcsv($handle, 10000, ",") ) !== FALSE )
{
$number_of_fields = count($data);
if ($current_row == 1)
{
//Header line
for ($c=0; $c < $number_of_fields; $c++)
{
$header_array[$c] = $data[$c];
}
}
else
{
//Data line
for ($c=0; $c < $number_of_fields; $c++)
{
$data_array[$header_array[$c]] = $data[$c];
}
/* Manufacturer title */
$manufacturerTitle = preg_replace('/[^A-Za-z0-9\-]/', '', $data_array['Manufacturer']);
$selectManufactures = "SELECT id, title FROM manufacturers";
$selectManufacturesExecute = $mysqli->query($selectManufactures);
$selectManufacturesFetch = $selectManufacturesExecute->fetch_array();
$selectManufacturesFetchTitle = preg_replace('/[^A-Za-z0-9\-]/', '', $selectManufacturesFetch['title']);
if( $selectManufacturesFetchTitle == $manufacturerTitle ){
$selectManufacturesFetchId = $selectManufacturesFetch['id'];
}
else {
$insert_manufacturer = "INSERT INTO manufacturers (title) VALUES ('".$manufacturerTitle."')";
$mysqli->query($insert_manufacturer);
$manufacturer_insert_id = $mysqli->insert_id;
}
}
$current_row++;
}
fclose($handle);
?>
Read first row from csv file and create table automatically according to it(csv file fields) in mysql. Looking for PHP script?
I have tried this
<?php
$arr = array(array(),array());
$num = 0;
$row = 0;
$handle = fopen("./contacts.csv", "r");
while($data = fgetcsv($handle,1000,",")){
$num = count($data);
for ($c=0; $c < $num; $c++) {
$arr[$row][$c] = $data[$c];
}
$row++;
}
$con = mysql_connect('localhost','root','');
mysql_select_db("excel_database",$con);
for($i=1; $i<$row; $i++){
$sql = "INSERT INTO contacts VALUES ('".$arr[$i][0]."','".$arr[$i][1]."','".$arr[$i][2]."','".$arr[$i][3]."','".$arr[$i][4]."','".$arr[$i][5]."')";
mysql_query($sql,$con);
}
?>
This is half way to your question.
<?php
$row = 1;
if (($handle = fopen("ab.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
?>
whith array_shift(file('filename.csv')) will give you the first line of the document filename.csv
Modifiying your script a bit, this should do the trick and create the table according to the csv header line:
$sql[] = array();
$handle = fopen($file, "r");
$header = fgetcsv($handle,1000,",");
if($header){
$header_sql = array();
foreach($header as $h){
$header_sql[] = '`'.$h.'` VARCHAR(255)';
}
$sql[] = 'CREATE TABLE `imported_csv` ('.implode(',',$header_sql).')';
while($data = fgetcsv($handle,1000,",")){
$sql[] = "INSERT INTO imported_csv VALUES ('".implode("','",$data)."')";
}
}
$con = mysql_connect('localhost','root','');
mysql_select_db("excel_database",$con);
foreach($sql as $s){
mysql_query($s,$con);
}
Here's a single function to give you an array: fgetcsv See Example #1 on that page for a basic script.
The table will just be a matter of looping over the contents ...
Aha, I finally parsed "table automatically according to it in mysql" and understood. Sorry. fgetcsv will return an array; just use that array to create your sql command. e.g. '...values (' . implode(',', $results_of_fgetcsv) . ')...'
If you want to visualize the table data, in html, you can create a table using PHP and data from csv reading the first line as headers. I use this function that you can try it!
function build_table($source){
$data = array();
$file = fopen($source, 'r');
while (($result = fgetcsv($file,0,";")) !== false){$data[] = $result;}
fclose($file);
//Now process the data and create table
$data_rows=#count($data[0]); //from the first row get the header name
$colum_trail="";
//Create the header part
for($i=0; $i<$data_rows;$i++){
$cell=$data[0][$i]; //each header
$colum_trail.="<th>$cell</th>";
}
////Create the table body contents
$table_cells="";
for($i=1; $i<count($data);$i++){
$table_cells.="<tr>";
$cell=$data[$i];
foreach($cell as $cell_value){
$cell_v=$cell_value;
$table_cells.="<td>$cell_v</td>";
}
$table_cells.="</tr>";
}
$table="<table><tr>$colum_trail</tr>$table_cells</table>";
echo "<style>td {border-bottom: 2px solid black;}</style>";
echo $table;
}
Then all you need is to after that code, call that function like this:
build_table("source.csv"); //then call the file you want to create table
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])."'";