turning db data into csv with header row in php - php

I have a script that turns a database query result into a csv file. The csv file's first row needs to be the field names of what's defined in the query. Here's what I have so far:
$fp = fopen('report.csv', 'w');
$column_names = array();
foreach($dbh->query($base_query, PDO::FETCH_ASSOC) as $row) {
if (empty($column_names)) {
$column_names = array_keys($row);
fputcsv($fp, $column_names);
}
// additional processing omitted ...
fputcsv($fp, $row);
}
fclose($fp);
Is there a nicer way to populate the column names in the first row of csv (do away with the if condition)? Perhaps do it outside of the loop? or have PDO output the column names before fetching data?
Thanks.

There is always a nicer way, if you separate different operations from each other.
//database part
$data = $dbh->query($base_query)->fetchAll();
// header part
$fp = fopen('report.csv', 'w');
$column_names = array_keys($data[0]);
fputcsv($fp, $column_names);
// body part
foreach($data as $row) {
// additional processing omitted ...
fputcsv($fp, $row);
}

Is there a nicer way to populate the column names in the first row of csv (do away with the if condition)?
No.
Perhaps do it outside of the loop?
Your code is inferring the column names from the keys of the fetched row and as such needs to be inside the loop.
PDO output the column names before fetching data?
This would require an additional query or storing metadata otherwise. Both of which are extra work.

Related

How to fetch database result as a stream using PHP/Zend Framework1

I'm writing a CSV file with the results from a function that returns database query results as an array, and getting memory out of exception if the result set is large.
So I'm looking for writing CSV using streams, can anyone help me how to do this using PHP or Zend Framework-1.
You have to change your function to return a statement, not full results. You can use fetch method to get database results per-row and fputcsv to write into a csv file.
$fp = fopen('file.csv', 'w');
$stmt = $db->query('SELECT * FROM table WHERE smth IS NOT NULL ORDER BY id DESC');
while ($row = $stmt->fetch()) {
fputcsv($fp, $fields);
}
fclose($fp);

output column names from custom query in mysql

I've created a small input form for a custom sql query using php. I've been able to output the results to a csv form, however I'm having some trouble including the headers in the output file.
I've had no trouble creating an array of the header rows, but I'd like to be able to create the headers out of the query itself.
This is what I've used:
$output = fopen('php://output', 'w');
//get query data
$qs = $_GET['custom'];
$rs = mysqli_query($dbc, $qs)
or die ('Error querying database');
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=query.csv');
$csv = fopen('php://output', 'w');
while ($row = mysqli_fetch_assoc($rs)) {
fputcsv($csv, $row);
}
fclose($csv);
What I want is a way of inputting the rows from the select before the content of the query (which comes through fine).
I know this will work for set headers if I put it in before the first fputcsv line:
fputcsv($csv, array('col1', 'col2', 'col3', [etc...] ));
but it is only because I define the fields in the array.
What I'm looking for is way to identify the columns in the query and use them as column headers.
I've been attempting to do something with a query that would just get the column names, and then feed that as an array but I can't seem to get it to work. Something like this:
SELECT column_name
FROM information_schema.columns
WHERE table_schema = 'database_name'
and column_name in ($query)
where the $query variable is similar to the $qs query above, but alas no luck. Does anyone know how to do this? Thanks in advance.
fputcsv($csv, array_keys($row)); at the beginning?

PHP create a complex CSV file

I am in need to create a CSV file getting the data from a mySQL DB.
The fact is that I want the CSV tp be corrected labeled and not just writing the data like this:
id,name,url
1,thisismyname,thisismyurl
I need the CSV file to look well ordered and each data inserted in the relative column.
Also with the function I am going to add below I can only grab the data from the DB and write it to the CSV file as it is. But I need to work with the data and have the CSV labeled in this way:
Campaign Name:
Name of the campaign
Campaign Url:
Url of the campaign
Tot visits:
Tot of visits
Tot unique visits:
Tot of unique visits
id name url
1 thisname this url
2 thisname this url
3 thisname this url
4 thisname this url
5 thisname this url
This is the PHP code I have so far..I need to understand how to achieve a correct structure of the CSV with PHP and adding the lines in it the exact way I want..
Thanks for your help!
function genCSV($filename, $attachment = true, $headers = true) {
// send response headers to the browser
header('Content-Type: text/csv');
header('Content-Disposition: attachment;filename=' . $filename);
$fp = fopen('php://output', 'w');
$query = "SELECT * FROM campaigns";
$result = mysql_query($query) or die(mysql_error());
if ($headers) {
// output header row (if at least one row exists)
$row = mysql_fetch_assoc($result);
if ($row) {
fputcsv($fp, array_keys($row));
// reset pointer back to beginning
mysql_data_seek($result, 0);
}
}
while ($row = mysql_fetch_assoc($result)) {
fputcsv($fp, $row);
}
fclose($fp);
}
Here is a much less elegant solution than the one proposed by #Tom Regner.
I needed to backup certain database tables (all those with a given prefix) but not others. This method, though somewhat slow, allows you to select exactly which tables and which columns from those tables are copied. It was originally written to allow each piece of data to be AES encrypted before being entered into the file but there are other uses for it. As written here, the result is a CSV file with the first line containing the list of columns for the table and the rest containing the data in CSV. It will stand adaptation to output the result of any sql into CSV, if you like.
Obviously: mysqlidb = mysqli databse resource, backups/ = directory to put finished files in.
FWIIW, here is the code:
$sql="SHOW TABLES LIKE 'yourtable%'";
$result = $mysqlidb->query($sql);
$tableresult=$mysqlidb->query($sql);
while($tables=$tableresult->fetch_assoc())
{
$keys=array_keys($tables);
$tablename=$tables[$keys[0]];
echo "Writing $tablename <BR>";
$file=fopen("backups/$tablename.enc","w");
$cols=array();
$sql="SHOW COLUMNS FROM $tablename";
$result=$mysqlidb->query($sql);
while($row=$result->fetch_assoc())
{
$cols[]=$row['Field'];
}
fputcsv($file,$cols);
$sql="SELECT * FROM $tablename";
$result=$mysqlidb->query($sql);
while($row=$result->fetch_assoc())
{
fputcsv($file,$row);
}
fclose($file);
}

Exporting Access Database into Text file through php

Scenario:
I am exporting a table Named "Registration" from access database and writing into a file named "isl.txt" in php using pdo. Fields separated by "," and Records separated by "\\"(i know it should be "\n" for convenience but it cant take a new line in text file. Don't know why !! so i have chosen "\\")
Registration Table in Access:
Roll_Num,Course,Marks,Discipline,Session
0,CS-101,89,CS,Fall94
0,CS-102,70,CS,Fall94
0,CS-103,59,CS,Fall94
Code:
$fl = fopen('isl.txt', 'w');
$db = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb)};DBQ=D:\Islamabad.mdb;Uid=;Pwd=;");
$results = $db->query("select * from `Registration`");
while ($row = $results->fetch()) {
foreach ($row as $value) {
$lastv = end($row);
if ($value != $lastv){
fwrite($fl, $value.",");
}
}
fwrite($fl, $value."\\");
}
fclose($fl);
Output:
0,0,CS-101,CS-101,89,89,CS,CS,Fall94\0,0,CS-102,CS-102,70,70,CS,CS,Fall94\0,0,CS-103,CS-103,59,59,CS,CS,Fall94
Problem:
As u see, every single value of record is repeating two times. Please Check whats wrong with my code!!
The repeating values are because you are not specifying a fetch_style in $results->fetch([fetch_style]). According to the manual - http://php.net/manual/en/pdostatement.fetch.php - when fetch_style is not specified, it defaults to value of PDO::ATTR_DEFAULT_FETCH_MODE (which defaults to PDO::FETCH_BOTH).
PDO::FETCH_BOTH (default): returns an array indexed by both column
name and 0-indexed column number as returned in your result set
Try changing to -
while ($row = $results->fetch(PDO::FETCH_ASSOC)) {
OR
while ($row = $results->fetch(PDO::FETCH_NUM)) {

Automatically build mySql table upon CSV upload

Automatically build mySql table upon a CSV file upload.
I have a admin section where admin can upload CSV files with different column count and different column name.
which it should then build a mySql table in the db which will read the first line and create the columns and then import the data accordingly.
I am aware of a similar issue, but this is different because of the following specs.
The name of the Table should be the name of the file (minus the extension [.csv])
each csv file can be diffrent
Should build a table with number of columns and names from the CSV file
add the the data from the second line and on
Here is a design sketch
Maybe there are known frameworks that makes this easy.
Thanks.
$file = 'filename.csv';
$table = 'table_name';
// get structure from csv and insert db
ini_set('auto_detect_line_endings',TRUE);
$handle = fopen($file,'r');
// first row, structure
if ( ($data = fgetcsv($handle) ) === FALSE ) {
echo "Cannot read from csv $file";die();
}
$fields = array();
$field_count = 0;
for($i=0;$i<count($data); $i++) {
$f = strtolower(trim($data[$i]));
if ($f) {
// normalize the field name, strip to 20 chars if too long
$f = substr(preg_replace ('/[^0-9a-z]/', '_', $f), 0, 20);
$field_count++;
$fields[] = $f.' VARCHAR(50)';
}
}
$sql = "CREATE TABLE $table (" . implode(', ', $fields) . ')';
echo $sql . "<br /><br />";
// $db->query($sql);
while ( ($data = fgetcsv($handle) ) !== FALSE ) {
$fields = array();
for($i=0;$i<$field_count; $i++) {
$fields[] = '\''.addslashes($data[$i]).'\'';
}
$sql = "Insert into $table values(" . implode(', ', $fields) . ')';
echo $sql;
// $db->query($sql);
}
fclose($handle);
ini_set('auto_detect_line_endings',FALSE);
Maybe this function will help you.
fgetcsv
(PHP 4, PHP 5)
fgetcsv — Gets line from file pointer
and parse for CSV fields
http://php.net/manual/en/function.fgetcsv.php
http://bytes.com/topic/mysql/answers/746696-create-mysql-table-field-headings-line-csv-file has a good example of how to do this.
The second example should put you on the right track, there isn't some automatic way to do it so your going to need to do a lil programming but it shouldn't be too hard once you implement that code as a starting point.
Building a table is a query like any other and theoretically you could get the names of your columns from the first row of a csv file.
However, there are some practical problems:
How would you know what data type a certain column is?
How would you know what the indexes are?
How would you get data out of the table / how would you know what column represents what?
As you can´t relate your new table to anything else, you are kind of defeating the purpose of a relational database so you might as well just keep and use the csv file.
What you are describing sounds like an ETL tool. Perhaps Google for MySQL ETL tools...You are going to have to decide what OS and style you want.
Or just write your own...

Categories