Inserting a table record (log entry) upon CSV download - php

I'm fairly new to PHP and this is my first-ever stackoverflow question:
I want to make it easy for a user to know when data has changed since they last downloaded a CSV file from the application I'm building. The CSV export works and I can determine whether there are any rows whose timestamp is after the timestamp stored in an export log table. My problem is that I cannot figure out how to store the timestamp in the log table. When a user clicks the link to export the file, the code below executes to produce the file. The very last four lines are my attempt to make the log entry. $con is valid and works and my method works in a regular PHP page, but I can't figure out how to make it work in the CSV download page and I don't know of any other way to make the entry when the user clicks to download. I am open to ideas for the best way to do this.
I really appreciate your time -- thanks in advance!
<?php
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=speakers.csv");
header("Pragma: no-cache");
header("Expires: 0");
require_once("../scripts/dbcon.inc.php");
require_once("../scripts/presentersessions.inc.php");
$query = "SELECT DISTINCT sp.person_id, CONCAT(p.person_display_name, ' ', p.person_last_name) person_name, '' session_titles, p.person_bio FROM person p INNER JOIN presenters sp ON p.person_id = sp.person_id ORDER BY p.person_last_name, p.person_display_name";
$result = mysqli_query($con, $query) or die('failed query: '.$query);
$num_rows = mysqli_num_rows($result);
$output = fopen("php://output", "w");
fputcsv($output, array("Item ID (Optional)","Name","Sub-Title (i.e. Location, Table/Booth, or Title/Sponsorship Level)","Description (Optional)","Location/Room"));
while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
#echo '"","'.htmlspecialchars($row['person_display_name']).' '.htmlspecialchars($row['person_last_name']).'","'.htmlspecialchars($row['session_title']).'","'.htmlspecialchars($row['person_bio']).'"\n"';
$person_id = $row['person_id'];
$row['person_name'] = $row['person_name'];
$row['session_titles'] = presenter_sessions($conference_id, $person_id);
$row['person_id'] = '';
fputcsv($output, $row);
}
date_default_timezone_set('US/Eastern');
$export_timestamp = date("Y-m-d H:i:s");
$query_insert_log_entry = "INSERT INTO export_log (export_type, export_timestamp, person_id) VALUES ('$export_type', '$export_timestamp', {$_SESSION['valid_accbo_person_id']})";
$result_insert_log_entry = mysqli_query($con, $query_insert_log_entry);

make sure you set this vaiable $export_type and $_SESSION['valid_accbo_person_id'] is accessible on this page.
I think the problem is in this line -
$query_insert_log_entry = "INSERT INTO export_log (export_type, export_timestamp, person_id) VALUES ('$export_type', '$export_timestamp', {$_SESSION['valid_accbo_person_id']})";
remove those single quote from variables like below -
$query_insert_log_entry = "INSERT INTO export_log (export_type, export_timestamp, person_id) VALUES ('{$export_type}', '{$export_timestamp}', '{$_SESSION['valid_accbo_person_id']}')";

Related

fputcsv adds unwanted Validation comment at top of file

I need csv output with column headers and comma delimited data. The fputcsv function is working right except that it places a "Validation" comment at the top of the output file:
<!-- Validated at 2016-04-17 00:32:00 -->
This line causes the file to fail when updating my data. If I remove the comment, the file works. Does anyone know how to generate fputcsv output without the comment line?
Here is code
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=gmail.csv');
$output = fopen('php://output', 'w');
fputcsv($output, array('Name', 'Given Name', 'Family Name', 'Group Membership', 'E-mail 1 - Value'));
// Connect to host and open db
include('includes/connect.php');
//Set Date range. Determines current renewal year for Select statement
$year = date('Y') - 1;
$group = date('Y')." member";
/* Select specified member data */
$sql = "SELECT firstLast, firstName, lastName, email, status, gmail, payDate
FROM membership, memberDues
WHERE payDate >= '$year-10-01' AND ID = memberID
ORDER BY lastName, firstName";
$result = mysqli_query($dbCnx, $sql);
while ($row = mysqli_fetch_assoc($result)) {
$gmailArray = array( $row['firstLast'], $row['firstName'], $row['lastName'], "$group", $row['email'] );
fputcsv($output, $gmailArray);}
I discovered the problem. My security include (which I hadn't looked at in a few years), inserts that Validation line if user has permission to view the page. I guess it's useful to review old bits of plug&play code every so often to help trouble shoot these types of annoyances.

Force a .txt file to download after creating list of mysql result

I want to download a file which includes the results of my mysql query but my problem is, the .txt file includes only the last result of my mysql query. It should includes actually 5 results like this:
http://user:password#server.com:8080
Can someone show me where here the problem is?
<?php
$result = mysql_query("SELECT serverurl FROM ibn");
echo mysql_error();
while ($row = mysql_fetch_array($result)) {
$result2 = mysql_query("SELECT streamport,streamname FROM streams");
echo mysql_error();
while ($row2 = mysql_fetch_array($result2)) {
$result3 = mysql_query("SELECT client_username,client_openpasswd FROM clients WHERE `client_id` = '$id' ");
echo mysql_error();
while ($row3 = mysql_fetch_array($result3)) {
$streamurl= $row['serverurl'];
$streamport = $row2['streamport'];
$streamuser= $row3['client_username'];
$streampassword= $row3['client_openpasswd'];
$streamchannel= $row2['streamname'];
echo "<p>http://$streamuser:$streampassword#$streamurl:$streamport</p>";
}
}
}
//Generate text file on the fly
header("Content-type: text/plain");
header("Content-Disposition: attachment; filename=bouquet.txt");
?>
Your basic output can be achieved by moving your calls to header() to the top of the script and emitting your data later. The header commands will only be effective if they're issued before any output is sent to the client.
You can demonstrate this with a simple script:
<?php
header("Content-type: text/plain");
header("Content-Disposition: attachment; filename=bouquet.txt");
echo "A line of text\n";
The remainder of your code is more problematic. It's not clear why you're doing this, but the effect of your code is to produce the cartesian product of the three tables. i.e. every row in every table is combined with every row in every other table. I doubt this is actually what you want, but...
You can achieve the same result more efficiently by using an SQL JOIN with no ON clause. Using that and concatenating the required fields you can do almost everything you want in a single SQL query:
select
concat('http://',
clientname,':',
clientopenpassword,'#',
serverurl,':',
streamsport)
as URL
from ibn, streams, clients where client_id=1
I'll leave converting this to a working PHP script as an exercise for the reader, but your code above provides a good template. Remember, only one query and one loop to fetch the result and emit it.
Note that mysql_*() is deprecated - use mysqli_*() for new code. You should also watch for possible SQL injection where you use $id in your query.

Run 2 sql query with 1 query for save query result as .csv format

In my web I've 2 page. 1) admin.php 2) csv.php. In admin.php page following query is showing data from db. In csv.php page I used same query to save data to .csv format but Can't save it.
I decided to run this same query in ONE QUERY. So that I can get the query result and can save it to csv format.
Questions:
1) How do i run this query to ONE query ?
2) Following query is showing data successfully. So how do i save it as .csv file ?
I search google for that and found many result which is showing how do I save data as .csv format with only one query. But you see that I've 2 while statement in my query then how do i save it as .csv format ? NO idea :(
Thanks and Looking for your help. :)
Note: I'm new learner about php and mysql.
$sqlagentdetails = "select * from users WHERE company_name != ''";
$rowresult = mysql_query($sqlagentdetails);
while($row = mysql_fetch_array($rowresult, MYSQL_ASSOC))
{
$pc1 = $row['pc1'];
$pc2 = $row['pc2'];
$pc3 = $row['pc3'];
$pc4 = $row['pc4'];
$emailAgent = $row['user_email'];
$user_id = $row['id'];
$myQuery = mysql_query("
SELECT *
FROM user_property upr
WHERE (postcode = '$pc1' OR
postcode = '$pc2' OR
postcode = '$pc3' OR
postcode = '$pc4') AND
datediff(CURDATE(), upr.creation_date) <= 7 AND
NOT EXISTS(SELECT ofr.property_id
FROM offers ofr
WHERE ofr.property_id = upr.property_id AND
ofr.agent_id IN(SELECT id
FROM users
WHERE company_name !=''
)
)
ORDER BY property_id DESC");
while($row = mysql_fetch_array($myQuery)){
// more data are goes to here...
}
}
1) How do i run this query to ONE query ?
You don't want it to run as one query. It's usually better to have lots of small simple queries instead of one complicated query. In fact I would suggest you update your code to have even more queries, for example the contents of the "not exists()" should not be done as a subquery, it should be a completely separate query to improve performance.
2) Following query is showing data successfully. So how do i save it as .csv file ?
There are two parts, first you need to send the correct HTTP headers to trigger a CSV download:
header('Content-type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename="export.csv";' );
Then just print out the data in CSV format:
while ($row = mysql_fetch_array($myQuery)) {
$first = true;
foreach ($row as $cell) {
if ($first)
$first = false;
else
print ',';
print '"' . addslashes($cell) . '"';
}
print "\n";
}
Note: CSV is a bad format, and this will only work in some editions of Microsoft Excel. Depending where the user lives (eg: Europe) it might not work properly. For most editions of Excel the above will work however. There is no good solution except to avoid using CSV.

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);
}

Export MySql table to CSV?

So, I have searched most of the answers here on stack and google and anywhere I could think of. There are plenty of answers indeed, but none have the structure I need.
Al my code looks like this:
$sql = "SELECT * FROM users WHERE user_level = '$level' ORDER BY user_username DESC";
if ($stmt = $this->connect->prepare($sql)) {
$stmt->bind_result($id);
$stmt->execute();
while ($row = $stmt->fetch()) {
$stmt->bind_result($id);
$users[] = $id;
}
$stmt->close();
$length[] = sizeof($users);
} else {
$error = true;
$message['error'] = true;
$message['message'] = CANNOT_PREPARE_DATABASE_CONNECTION_MESSAGE;
return json_encode($message);
}
I'm using mysqli and stmt in all of my code, so I would like to keep it like this all the way.
So, I understand that I cannot have the CSV file where I have my action button to download it. But the thing is that my action button is part of a form, so I guess that instead of $_GET on the page I have the CSV I will have $_POST.
And my question, how do I loop through all database ( this needs to be depending on a column, a level ) and take all that data organized in a CSV file and than download it ? But this needs to be as the structure I have for my functions, I don't want to use db_query("SELECT * FROM {loreal_salons}"); per say or other like that.
Use the following :
// Setup the headers to force download of CSV
header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=file.csv");
header("Pragma: no-cache");
header("Expires: 0");
// loop your records here and output as comma separated
echo $row['col1'].",".$row['col3'].",".$row['col3']."\n";
If you want to loop over all the database, I think the key for what you want to do is :
SHOW TABLES - http://dev.mysql.com/doc/refman/4.1/en/show-tables.html
.. to loop in all the tables
SHOW COLUMN - http://dev.mysql.com/doc/refman/5.0/en/show-columns.html
.. to loop in all the column of a specific table

Categories