Use multiple SQL queries to output into CSV format using PHP - php

having some issues outputting some SQL queries into CSV format. I can successfully do one query and write it to CSV, but I need to do a query within a query and I get that awesome infinite loop. Here's what I have so far
header( 'Content-Type: text/csv' );
header( 'Content-Disposition: attachment;filename='.$filename);
$fp = fopen('php://output', 'w');
$result = mysqli_query($conn, "SELECT * FROM Customers")
or die("Error: ".mysqli_error($conn));
$row = mysqli_fetch_assoc($result);
if($row) {
fputcsv($fp, array_keys($row));
// reset pointer back to beginning
mysqli_data_seek($result, 0);
}
while($row = mysqli_fetch_assoc($result)) {
$orderResult = mysqli_query($conn,"SELECT * FROM Orders WHERE order_No = '".$row['customer_ID']."'")
or die("Error: ".mysqli_error($conn));
$rowOrder = mysqli_fetch_assoc($orderResult);
fputcsv($fp, array_keys($rowOrder));
mysqli_data_seek($result, 0);
$rowOrder = mysqli_fetch_assoc($orderResult);
fputcsv($fp, $row);
fputcsv($fp, $rowOrder);
}
fclose($fp);
The output i'm trying to achieve is:
Display customer header info in this row a.k.a first name, surname, email
next row displays info about customers e.g Tony, Mcguire, tony#b.c
Display Tony's order header info e.g order number, order date
display Tony's order info e.g 5122, 6/3/2013
If I can get it all to display into 2 rows, that'd be even better.

This can be cleaned up a lot. If I'm understanding you right, you want to generate a report where row 1 is the header and each row after is customer/order data. This is an example I came up with:
$sql = "SELECT c.*, o.* FROM Customers AS c
JOIN Orders AS o ON c.CustomerID = o.CustomerID";
$result = mysqli_query($conn, $sql);
$i = 1;
while($row = mysqli_fetch_assoc($result)) {
if ($i == 1) {
// this is the header
fputcsv($fp, array_keys($row));
$i++;
}
// this is the customer/order data
fputcsv($fp, $row);
}
You can specify which database fields you want to include by replacing the c.* with the customer fields (c.name, c.address, etc) and the o.* with your order fields (o.orderid, o.date, etc)

Related

How to update specific column using fgetcsv

I'm trying to update a specific column through fgetcsv. But the problem is all the data are the same. Can someone help me about this? I don't know how to make the use of grade_id here because there are no grade_id in csv only in the database. And im doing it with only just file uploading.
Here's the csv. I just only want the midterm grade to be updated. But only the value 64 is inserted.
here's the result. The output should be 75,80,64 not 64,64,64
here's my database structure
here's my code
if(isset($_POST["Import"])){
$term = $_POST['term'];
$fac_code = $_POST['fac_code'];
$sch_year = $_POST['schoolyear'];
$section = $_POST['sec'];
$semester = $_POST['semester'];
$sub = $_POST['sub'];
echo $filename=$_FILES["file"]["tmp_name"];
$heading = true;
if($_FILES["file"]["size"] > 0)
{
$file = fopen($filename, "r");
while (($emapData = fgetcsv($file, 10000, ",")) !== FALSE)
{
if($heading) {
// unset the heading flag
$heading = false;
// skip the loop
continue;
}
//to get the last column
$last = end($emapData);
$sql1 ="SELECT * FROM grade WHERE subj_descr ='$sub' AND section = '$section'";
$result = mysqli_query($con, $sql1);
while($row = mysqli_fetch_array($result)){
$gradeid = $row['grade_id'];
$sql = "UPDATE grade SET midterm_grade = '$last' WHERE grade_id = '$grade_id'";
$result = mysqli_query( $con, $sql );
}
}
fclose($file);
//throws a message if data successfully imported to mysql database from excel file
echo "<script type=\"text/javascript\">
alert(\"CSV File has been successfully Imported.\");
window.location = \"homefaculty.php\"
</script>";
//close of connection
mysqli_close($con);
}
}
Your loop for updating in mysql is done just after your fetch your last value
In means in your code you do 3 loops for updating all value
$sql1 ="SELECT * FROM grade WHERE subj_descr ='$sub' AND section = '$section'";
This loop which fetch always the same result is called 3 times.
"UPDATE grade SET midterm_grade = '$last' WHERE grade_id = '$grade_id'";
In this query the grade_id comes from all the resultset
Basically you are doing this
1- get the last value of the line of CSV
2- select all records
3- update all of them with the value of 1-
4- next line
Instead of looping in all you mysql database for the SELECT, you should be able to SELECT just the record you need. I don't know if your CSV is full but do you have the grade_id in a column ? Otherwise how can you match a row of your CSV to a record in your database ?
EDIT
after discussion you said you have a unique key on section, term and subject
(You have to identify a relation between a row in CSV and a row in your database)
$last = end($emapData); //to get the last column
$section = $emapData[0]; // assuming section is the first column of CSV
$term = $emapData[1]; // assuming term is the 2nd column of CSV
$subject = $emapData[2]; // assuming subject is the 3rd column of CSV
$sql = "UPDATE grade SET midterm_grade = '$last' WHERE section = '$section' AND term = '$term' AND subject = '$subject'";
$result = mysqli_query( $con, $sql );

PHP fputcsv not Outputting First Row From SQL Query (Outputs all Other Rows After the First Row)

I am using the very simple code below to export a CSV of all of my MySQL table's data, "members". However, there is a total of 560 rows in the MySQL table, but the CSV only shows 559 of the MySQL table's rows (it does not display the very first database's table's row). Does anyone know why this is, or perhaps what I can change in my code in order to fix this issue?
// BEGIN EXPORT ALL FROM EDITOR
if(isset($_POST['export_csv'])) {
$today_date = date('Y-m-d_h-i-s-a', time());
$FileName = "download/report_mailing_list_export_".$today_date.".csv";
$file = fopen($FileName,"w");
$sql = mysqli_query($dbc, "SELECT * FROM member WHERE memberid != 1 AND deleted=0 AND website = 0 ORDER BY last_name, first_name DESC");
$row = mysqli_fetch_assoc($sql);
// Save headings alon
$HeadingsArray=array();
foreach($row as $name => $value){
$HeadingsArray[]=$name;
}
fputcsv($file,$HeadingsArray);
// Save all records without headings
while($row = mysqli_fetch_assoc($sql)){
$valuesArray=array();
foreach($row as $name => $value){
$valuesArray[]=$value;
}
fputcsv($file,$valuesArray);
}
fclose($file);
header("Location: $FileName");
}
// END EXPORT
You calling mysqli_fetch_assoc($sql); before while loop, which iterates over first row. You may change it to something like this:
// BEGIN EXPORT ALL FROM EDITOR
if(isset($_POST['export_csv'])) {
$today_date = date('Y-m-d_h-i-s-a', time());
$FileName = "download/report_mailing_list_export_".$today_date.".csv";
$file = fopen($FileName,"w");
$sql = mysqli_query($dbc, "SELECT * FROM member WHERE memberid != 1 AND deleted=0 AND website = 0 ORDER BY last_name, first_name DESC");
$row = mysqli_fetch_assoc($sql);
// Save headings alon
$HeadingsArray=array();
foreach($row as $name => $value){
$HeadingsArray[]=$name;
}
fputcsv($file,$HeadingsArray);
// Save all records without headings
do {
$valuesArray=array();
foreach($row as $name => $value){
$valuesArray[]=$value;
}
fputcsv($file,$valuesArray);
} while($row = mysqli_fetch_assoc($sql));
fclose($file);
header("Location: $FileName");
}
// END EXPORT
In this case, you will reuse $row from first iteration.

create multiple csv files using mysql & php while

i'm trying to generate multiple progressive csv file (with name DOC_n°.csv) using mysql & php while.
//query 1
$query2 ="SELECT id_order FROM ps_orders";
$result2= mysql_query($query2);
$i=1;
while ($riga2 = mysql_fetch_array($result2)){
//query 2
$query = "SELECT ps_order_detail.product_name,ps_orders.id_order,ps_orders.date_add,ps_order_detail.unit_price_tax_incl,ps_order_detail.id_order_detail,ps_order_detail.product_quantity,ps_order_detail.product_reference,ps_order_detail.product_weight,ps_order_detail.unit_price_tax_incl,ps_address.id_customer,ps_address.firstname,ps_address.lastname,ps_address.address1,ps_address.address2,ps_address.postcode,ps_address.city
FROM ps_orders
JOIN ps_order_detail ON ps_orders.id_order = ps_order_detail.id_order
JOIN ps_address ON ps_orders.id_customer = ps_address.id_customer
WHERE ps_orders.id_order=$i;";
$result = mysql_query($query);
//second while to write document and values inside of it
while ($riga = mysql_fetch_array($result)){
//useful variable to write files
$path ="TMPIN/";
$doc=$path."DOC_".$i.".csv";
$myfile = fopen($doc, "w");
...
...
information inside the csv
...
..
fwrite($myfile, $testo."\n");
fclose($myfile);
};
$i++;
};
My code works, but in the csv file generated i find all the loops generate before. There is a way to see only the LAST loop generat for cycle?
You have 2 while loop. You change file name only in the master loop, so in the child loop, you always write in the same csv (and massively open/close this file by the way !)
So you should try something like this :
$query = "SELECT ps_order_detail.product_name,ps_orders.id_order,ps_orders.date_add,ps_order_detail.unit_price_tax_incl,ps_order_detail.id_order_detail,ps_order_detail.product_quantity,ps_order_detail.product_reference,ps_order_detail.product_weight,ps_order_detail.unit_price_tax_incl,ps_address.id_customer,ps_address.firstname,ps_address.lastname,ps_address.address1,ps_address.address2,ps_address.postcode,ps_address.city
FROM ps_orders
JOIN ps_order_detail ON ps_orders.id_order = ps_order_detail.id_order
JOIN ps_address ON ps_orders.id_customer = ps_address.id_customer
WHERE 1=1;";
$result = mysql_query($query);
//second while to write document and values inside of it
while ($riga = mysql_fetch_array($result)){
$testo = "";
$testo .= "stuff to write\n";
...
...
information inside the csv
...
...
// once you know what to write, open file.
//useful variable to write files
$path ="TMPIN/";
$doc=$path."DOC_".$riga['id_order'].".csv";
$myfile = fopen($doc, "w");
fwrite($myfile, $testo."\n");
fclose($myfile);
}
EDIT : (Thanks to #Kickstart)
Deleted the first loop which is useless... You can do 1 only query
Your loop is set up wrong, and the core logic is highly inefficient as well. You should learn how to use JOINs.
In any case, to fix your code
while(... main query loop) {
$file = fopen(...);
$subquery = mysql_query(...);
while($row = mysql_fetch_array($subquery)) {
fputcsv($file, $subquery);
}
fclose($file);
}
Note how the fopen/close are OUTSIDE the inner loop.
Eliminating the extra loop, and only outputting the details for each id_order. Just outputs the file when the id_order changes.
<?php
//query 2
$query = "SELECT ps_order_detail.product_name,ps_orders.id_order,ps_orders.date_add,ps_order_detail.unit_price_tax_incl,ps_order_detail.id_order_detail,ps_order_detail.product_quantity,ps_order_detail.product_reference,ps_order_detail.product_weight,ps_order_detail.unit_price_tax_incl,ps_address.id_customer,ps_address.firstname,ps_address.lastname,ps_address.address1,ps_address.address2,ps_address.postcode,ps_address.city
FROM ps_orders
JOIN ps_order_detail ON ps_orders.id_order = ps_order_detail.id_order
JOIN ps_address ON ps_orders.id_customer = ps_address.id_customer
ORDER BY ps_orders.id_order";
$result = mysql_query($query);
//second while to write document and values inside of it
$last_id_order = 0;
while ($riga = mysql_fetch_array($result))
{
if ($last_id_order != $riga['id_order'] and $last_id_order != 0)
{
output_file($testo, $last_id_order);
$testo = '';
$last_id_order = $riga['id_order'];
}
//useful variable to write files
...
...
information inside the csv
...
..
}
if ($last_id_order != 0)
{
output_file($testo, $last_id_order);
}
function output_file($testo, $last_id_order)
{
//useful variable to write files
$path = "TMPIN/";
$doc = $path."DOC_".$last_id_order.".csv";
$myfile = fopen($doc, "w");
fwrite($myfile, $testo."\n");
fclose($myfile);
}

Adding another JOIN to query and getting table column titles

I am working on a data to CSV function but I'm stuck.
So far it's getting all data from two tables and putting onto a CSV file all in 1 line for each order with invoice data and customer data .
I need to also get invoice_items by ID as well (those I guess will need to be looped as might have more than 1 item but unsure how to add invoice_items to the query and also I need to set the titles as well for the columns but unsure how).
It would be awesome if it could be like this:
|invoice details customer details | invoice items
LIST ITEM
LIST ITEM
LIST ITEM
rather than
invoice details | customer details | invoice items LIST ITEM LIST ITEM
LIST ITEM
with real data and titles would look something like
id | invoice number | amount | name | address | invoice items (and
list below this part)
PHP
header("Content-type: text/csv");
// output any connection error
if ($mysqli->connect_error) {
die('Error : ('.$mysqli->connect_errno .') '. $mysqli->connect_error);
}
$file_name = 'invoice-export-'.date('d-m-Y').'.csv'; // file name
$file_path = 'downloads/'.$file_name; // file path
$file = fopen($file_path, "w"); // open a file in write mode
chmod($file_path, 0777); // set the file permission
$query_table_columns_data = "SELECT *
FROM invoices i
JOIN customers c
ON c.invoice = i.invoice
WHERE i.invoice = c.invoice
ORDER BY i.invoice";
if ($result_column_data = mysqli_query($mysqli, $query_table_columns_data)) {
// fetch table fields data
while ($column_data = $result_column_data->fetch_row()) {
$table_column_data = array();
foreach($column_data as $data) {
$table_column_data[] = $data;
}
// Format array as CSV and write to file pointer
fputcsv($file, $table_column_data, ",", '"');
}
}
If I understand you correctly, you need to join to another table to get the invoice items.
I also suspect that your current example query is joining the tables incorrectly, as you appear to be joining the customers and invoices tables based on the invoice. As I expect a customer could have many invoices, but an invoice only has one customer I would expect the invoice table to store the relevant customer id, and then do a join based on that.
As such you could get the details with something like this:-
SELECT i.id,
i.invoice_number,
i.amount,
c.name,
c.address,
ii.invoice_item
FROM invoices i
INNER JOIN customers c
ON c.id = i.customer_id
INNER JOIN invoice_items ii
ON ii.invoice_id = i.id
ORDER BY i.invoice
Note I have switched from SELECT * to selecting the column names (which I am guessing at), as SELECT * is frowned upon for various reasons. You could alias the column names if you wanted something more readable.
But you want a list of titles taken from the column names. Assuming you do not want to just hardcode these I would suggest that you switch from using mysqli_fetch_row to mysqli_fetch_assoc, which will return the column names.
You can then process the column names on the first row and output those. Something like this:-
<?php
header("Content-type: text/csv");
// output any connection error
if ($mysqli->connect_error) {
die('Error : ('.$mysqli->connect_errno .') '. $mysqli->connect_error);
}
$file_name = 'invoice-export-'.date('d-m-Y').'.csv'; // file name
$file_path = 'downloads/'.$file_name; // file path
$file = fopen($file_path, "w"); // open a file in write mode
chmod($file_path, 0777); // set the file permission
$query_table_columns_data = "SELECT i.id,
i.invoice_number,
i.amount,
c.name,
c.address,
ii.invoice_item
FROM invoices i
INNER JOIN customers c
ON c.id = i.customer_id
INNER JOIN invoice_items ii
ON ii.invoice_id = i.id
ORDER BY i.invoice";
if ($result_column_data = mysqli_query($mysqli, $query_table_columns_data))
{
// fetch table fields data
if ($column_data = $result_column_data->fetch_assoc())
{
$table_column_head = array();
$table_column_data = array();
foreach($column_data as $field_name->$data)
{
$table_column_head[] = $field_name;
$table_column_data[] = $data;
}
// Format array as CSV and write to file pointer
fputcsv($file, $table_column_head, ",", '"');
fputcsv($file, $table_column_data, ",", '"');
while ($column_data = $result_column_data->fetch_assoc())
{
$table_column_data = array();
foreach($column_data as $data)
{
$table_column_data[] = $data;
}
// Format array as CSV and write to file pointer
fputcsv($file, $table_column_data, ",", '"');
}
}
}
Expanding that a bit to only put out the invoice details on the first row for an invoice
<?php
header("Content-type: text/csv");
// output any connection error
if ($mysqli->connect_error) {
die('Error : ('.$mysqli->connect_errno .') '. $mysqli->connect_error);
}
$file_name = 'invoice-export-'.date('d-m-Y').'.csv'; // file name
$file_path = 'downloads/'.$file_name; // file path
$file = fopen($file_path, "w"); // open a file in write mode
chmod($file_path, 0777); // set the file permission
$query_table_columns_data = "SELECT i.id,
i.invoice_number,
i.amount,
c.name,
c.address,
ii.invoice_item
FROM invoices i
INNER JOIN customers c
ON c.id = i.customer_id
INNER JOIN invoice_items ii
ON ii.invoice_id = i.id
ORDER BY i.invoice";
if ($result_column_data = mysqli_query($mysqli, $query_table_columns_data))
{
// fetch table fields data
if ($column_data = $result_column_data->fetch_assoc())
{
$table_column_head = array();
$table_column_data = array();
foreach($column_data as $field_name->$data)
{
$table_column_head[] = $field_name;
$table_column_data[] = $data;
}
$prev_id = $column_data['id'];
$prev_invoice_number = $column_data['invoice_number'];
$prev_amount = $column_data['amount'];
$prev_name = $column_data['name'];
$prev_address = $column_data['address'];
// Format array as CSV and write to file pointer
fputcsv($file, $table_column_head, ",", '"');
fputcsv($file, $table_column_data, ",", '"');
while ($column_data = $result_column_data->fetch_assoc())
{
if ($prev_id == $column_data['id'] AND $prev_invoice_number == $column_data['invoice_number'] AND $prev_amount == $column_data['amount'] AND $prev_name == $column_data['name'] AND $prev_address == $column_data['address'])
{
$different_invoice = true;
}
else
{
$different_invoice = false;
$prev_id = $column_data['id'];
$prev_invoice_number = $column_data['invoice_number'];
$prev_amount = $column_data['amount'];
$prev_name = $column_data['name'];
$prev_address = $column_data['address'];
}
$table_column_data = array();
foreach($column_data as $field_name->$data)
{
$table_column_data[] = (($different_invoice or $field_name == 'invoice_item') ? $data : '');
}
// Format array as CSV and write to file pointer
fputcsv($file, $table_column_data, ",", '"');
}
}
}

Storing multiple rows from MySQL in separate variables

I am writing a web application in PHP which will store employee data and generate employee ID cards to PDF. I am using FPDF for creation of PDFs and that works fine. I am having a problem with showing results from MySQL database.
I have to generate PDF with 4 employee ID cards and I am not sure how to get them from the database. So far I am using LIMIT option in the query to get only 4 results and i will have an if statement based on mysql.php?id=1 id which will define the limit. It is a little messy but there are not going to be more than 80 employees.
This is my code:
$id = $_GET['id'];
if ($id == 1) {
$limit_start = 0;
$limit_end = 4;
}
$result=mysql_query("SELECT users.tajemnik, users.dateCreated, users.showmeID,
users.workerName, users.dateCreated, users.workerPlace, users.workerSID, uploads.userID, uploads.data, uploads.filetype
FROM users INNER JOIN uploads ON users.showmeID = uploads.userID ORDER BY workerName DESC LIMIT $limit_start, $limit_end") or die (mysql_error());
mysql_query("SET NAMES 'utf8'") or die('Spojení se nezdařilo');
while($row = mysql_fetch_array($result)){
$workerName = $row["workerName"];
$workerPlace = $row["workerPlace"];
$workerSID = $row["workerSID"];
$tajemnik = $row["tajemnik"];
$showmeID = $row["showmeID"];
$mysqldatetime = strtotime($row['dateCreated']);
$image = $row["data"];
$phpdatetime = date("d.m.Y",$mysqldatetime);
}
This will get me the first result from the query. I need to get information from all 4 rows and have them stored in variables like $workerName1, $workerName2 etc. I hope it makes sense what I am trying to do.
Thank you for your replies!
V.
I need to get variables like $workerName1, $workerName2 etc
Nope, you don't.
You actually need an array.
So, first, get yourself a function
function sqlArr($sql){
$ret = array();
$res = mysql_query($sql) or trigger_error(mysql_error()." ".$sql);
if ($res) {
while($row = mysql_fetch_array($res)){
$ret[] = $row;
}
}
return $ret;
}
then write a code
mysql_query("SET NAMES 'utf8'") or die('Spojení se nezdařilo');
$sql = "SELECT users.tajemnik, users.dateCreated, users.showmeID, users.workerName,
users.dateCreated, users.workerPlace, users.workerSID, uploads.userID,
uploads.data, uploads.filetype
FROM users
INNER JOIN uploads ON users.showmeID = uploads.userID
ORDER BY workerName DESC LIMIT $limit_start, $limit_end";
$data = sqlArr($sql);
Now you have all your data in the $data array.
So, you can loop over it or access single values like
echo $data[0]['tajemnik'];
or
foreach($data as $row) {
//do whatever you want with database row
echo $row['tajemnik'];
}

Categories