PHP create a complex CSV file - php

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

Related

Download to root and after delete files from database

I have this function, and this deletes textfiles after a certain age from my database automatically.
$r = new textfiles;
$db = new DB;
$currTime_ori = $db->queryOneRow("SELECT NOW() as now");
...
if($this->site->textfilesretentiondays != 0)
{
echo "PostPrc : Deleting textfiles older than ".$this->site->textfilesretentiondays." days\n";
$result = $db->query(sprintf("select ID from textfiles where postdate < %s - interval %d day", $db->escapeString($currTime_ori["now"]), $this->site->textfilesretentiondays));
foreach ($result as $row)
$r->delete($row["ID"]);
}
Now I would edit this function so that at first all textfiles are automatically downloaded in a root directory /www/backup and then the script should delete the textfiles with the string $r->delete($row["ID"]);
At the moment I have no idea how I could implement this.
For me it's seems to be impossible to give you an completely answer to your question because leak of informations.
Do you store the whole file-content in database or only the path and filename?
It would help us to see whats the content of "$row" which represents one row from database.
If you just store the filename (and optionally the path) you could use the "copy" (http://php.net/manual/de/function.copy.php) function from php to copy the file to your backup-directory. Please note, you have to ensure that the user who's executing the script or running the web-server have the privileges to write into the directory.
You could add this functionality to class textfiles as as method like makeBackup.
There are few information, but I'll give it a try. If you want to backup the rows before deleting them, you can store them in .txt file in json_encoded form using this piece of code inserted in the FOREACH loop, before delete command:
$myfile = fopen("/www/backup/".$row["ID"].".txt", "w") or die("Unable to open file!");
$txt = json_encode($row);
fwrite($myfile, $txt);
fclose($myfile);
By your approach ..
function delete ($id){
$result = $db->query(sprintf("select * from textfiles where id=$id);
//if you have filepath use copy as SebTM suggested
$path = $row['path']; //assuming path is the column name in ur db
$filename = basename($path); //to get filename
$backup_location = '/www/backup/'.$filename;
copy($path, $backup_location);
//if you have data in db
$content = $row['data'] //assuming data to be backed up to file is in a field 'data'
$backup_location = '/www/backup/file.txt';
file_put_contents($backup_location, $content);
}
But this is not the most optimal approach , you could shift even the initial query into delete function above , and call delete function only once, instead of calling it in a loop ..

Error in reading Excel file & Insert data into MySQL Database using PHP

My purpose is to read an excel (.xls) file and store it in the database as well as show the inputs of excel file in the browser.
I am facing problem while reading the file. I have integrated Excelfilereader.php
The program reads the excel file but while printing its output in (excel file content) in the browser, data print in zig-zag way.
Example:
studentid name class school course address [name of fields]
In Browser, the same fields are printed, but the data of studentID is printed under the name, data of name prints under class, but rest all are printed as it is. In first two columns are printed unaligned.
Code used to call Excelreader.php:
[mysql_query("insert into submit_form(parent_id,name,lab,submission,title,sampletype,file) values('','".$_POST['name']."','".$_POST['lab']."','".$_POST['submission']."','".$_POST['title']."','".$_POST['sampletype']."','".$uploadfile."')");
$insertid=mysql_insert_id();
$data = new Spreadsheet_Excel_Reader($_FILES['uploadfile']['name']);
//echo "Total Sheets in this xls file: ".count($data->sheets)."<br /><br />";
$html="<table border='1'>";
for($i=0;$i<count($data->sheets);$i++) // Loop to get all sheets in a file.
{
if(count($data->sheets[$i][cells])>0) // checking sheet not empty
{
//echo "Sheet $i:<br /><br />Total rows in sheet $i ".count($data->sheets[$i][cells])."<br />";
for($j=2;$j<=count($data->sheets[$i][cells]);$j++) // loop used to get each row of the sheet
{
$html.="<tr>";
for($k=1;$k<=count($data->sheets[$i][cells][$j]);$k++) // This loop is created to get data in a table format.
{
$html.="<td>";
$html.=$data->sheets[$i][cells][$j][$k];
$html.="</td>";
}
$data->sheets[$i][cells][$j][1];
$eid = $eid = mysqli_real_escape_string($connection,$data->sheets[$i][cells][$j][1]);
$age = mysqli_real_escape_string($connection,$data->sheets[$i][cells][$j][2]);
$gender = mysqli_real_escape_string($connection,$data->sheets[$i][cells][$j][3]);
$ethnic = mysqli_real_escape_string($connection,$data->sheets[$i][cells][$j][4]);
$cancer = mysqli_real_escape_string($connection,$data->sheets[$i][cells][$j][5]);
$sample = mysqli_real_escape_string($connection,$data->sheets[$i][cells][$j][6]);
$instrument = mysqli_real_escape_string($connection,$data->sheets[$i][cells][$j][7]);
$instrumenttype = mysqli_real_escape_string($connection,$data->sheets[$i][cells][$j][8]);
$query = "insert into submit_form(parent_id,name,lab,submission,title,patient,age,gender,ethnic,cancer,sample,instrument,instrumenttype,attach,sampletype,file) values('".$insertid."','".$_POST['name']."','".$_POST['lab']."','".$_POST['submission']."','".$_POST['title']."','".$eid."','".$age."','".$gender."','".$ethnic."','".$cancer."','".$sample."','".$instrument."','".$instrumenttype."','1','".$_POST['sampletype']."','".$uploadfile."')";
mysqli_query($connection,$query);
$html.="</tr>";
}
}][2]
You have mixed mysql_* calls with mysqli_* calls. Use only mysqli_* calls.
(And you should escape the $_POST[] columns, too. They are vulnerable to hackers.)

checking a condition through data inside a textfile

I have been using a redirect feature in my website where users are redirected to sites which are white listed. I realized that the procedure to authenticate the domain names through traditional db calls are much time consuming therefore I introduced a method to get the db table written to a text file and do the redirecting authentication from there by match the domain names. so I got the table of white listed domain names to a text file(serialized) as follows
code
$trusted_domain = $_GET['go'];//these variables are taken from the url
$project_id = $_GET['project'];//these variables are taken from the url
$query = "SELECT projectid, domainname FROM domains";
$result = mysql_query($query);
while($row= mysql_fetch_assoc($result)){
$objData = $objData." ". serialize( $row). "\r\n";
}
$filePath = "data.txt";
if (is_writable($filePath)) {
$fp = fopen($filePath, "w");
fwrite($fp, $objData);
fclose($fp);
}
the textfile content
a:2:{s:9:"projectid";s:2:"19";s:10:"domainname";s:27:"_http._sctp.www.example.com";}
a:2:{s:9:"projectid";s:2:"28";s:10:"domainname";s:11:"www.abc.com";}
a:2:{s:9:"projectid";s:2:"46";s:10:"domainname";s:11:"www.abc.com";}
a:2:{s:9:"projectid";s:2:"70";s:10:"domainname";s:12:"www.test.com";}
a:2:{s:9:"projectid";s:2:"75";s:10:"domainname";s:15:"www.bulding.com";}
a:2:{s:9:"projectid";s:2:"80";s:10:"domainname";s:11:"www.abc.com";}
a:2:{s:9:"projectid";s:2:"82";s:10:"domainname";s:11:"www.abc.com";}
a:2:{s:9:"projectid";s:3:"100";s:10:"domainname";s:47:"https://www.google.com
https://www.facebook.com";}
Now the problem is, can anyone tell me how to match the two variables $trusted_domain and $project_id with each and every projectid and domainname inside the serialized text above. I mean if a user comes with a url
http://trackme.domain.com/redirect?project=75&go=www.building.com
how do I compare the values 75 and www.building.com with content in the text file.
I would consider setting up a Memcache server for this, especially if you have lots of domains in the list.
I think the following will work for you though if you are flexible about the data format of the saved file. This example uses JSON which is quicker and easier to process.
$query = "SELECT projectid, domainname FROM domains";
$result = mysql_query($query);
$objData = [];
while ($row = mysql_fetch_assoc($result)){
$objData[$row['projectid']] = $row['domainname'];
}
file_put_contents('data.txt', json_encode($objData));
And then you can process like so:
$trusted_domain = $_GET['go'];//these variables are taken from the url
$project_id = $_GET['project'];//these variables are taken from the url
$data = json_decode(file_get_contents('data.txt'), true);
if (isset($data[$project_id]) && $data[$project_id] === $trusted_domain)
{
// Domain matches
}
When the JSON is read it creates an array where the project id is the key and the value is the domain name.
I have assumed here that the project_id is unique and there is only 1 trusted domain per project. If that's not the case, you may have to tweak this a little for your exact needs. E.g:
while ($row = mysql_fetch_assoc($result)){
$objData[$row['projectid']][] = $row['domainname'];
}
Notice the extra []? This will create an array of domain names for the project id, you can then use this when parsing the file:
if (isset($data[$project_id]) && in_array($trusted_domain, $data[$project_id])) { }
Also I should add, avoid using mysql_* functions as they are being deprecated. Look into PDO instead.

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.

How to run a mysql loop from a posted array and extract results to a CSV file

I have searched for hours to try and find a simple answer to this query I am having. I'm very sure it is covered in many ways, by other answers at least partially. I need a clear answer specific to what I am doing because I'm having difficulty trying to put together an answer that works for me from a bunch of other differently formatted and structured questions/answers.
I have a form which is posting a range of results intended to be used as keys for a mysql lookup loop. This is working fine - my post results in a successful array. For example:
$payarr = $_POST['pay'];
print_r($payarr);
Results in:
Array ( [0] => 12 [1] => 7 [2] => 1 )
Which is good given that the I want to run a mysqli process select the rows where claim_id is each of the values in $payarr. I then want to use fputcsv to write each of these rows fully, into a CSV file that is uniquely named by the days date and time that this is all run.
I have fragments of code that don't work and my frustration at trying to cobble something together that does work is getting a bit nuts. Can someone please show me how to do this effectively?
At the moment my code looks like this (but fails miserably):
<?php
include ("../conf/dbconfig.php");
include ("../conf/funcs.php");
include ("../conf/privs.php");
if($privs == 500) {
$view = $_POST['view'];
$payarr = $_POST['pay'];
$ts = date('Ymd-His');
print_r($payarr); //Testing to make sure our array to select from has arrived here ok.
//ob_start();
$fp = fopen('../csv/ResultsFile_'.$ts.'.csv', 'w');
foreach($payarr as $val) {
$result = mysqli_query($con, "'SELECT * FROM claims' WHERE claim_id='$val'");
//$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
while ($row = mysqli_fetch_array($result)) {
echo $payarr;
echo $val;
//fputcsv($fp, $row);
print_r($row);
}
}
fclose($fp);
// return ob_get_clean();
} else {
header("Location: http://www.google.com.au/");
die;
}
?>
I'm willing (and happy) to rewrite the entire thing just as long as it works, so any help and suggestions are very appreciated!
Thanks in advance.
BTW - The $view value is not important in this process but is here as it will be passed back to the resulting header once this all works.
A few rough suggestions (you may need to adapt):
1) Change your query to use IN for the possible values, so you only have to execute one DB query:
$result = mysqli_query($con, "SELECT * FROM claims WHERE claim_id IN (" . implode(",",$payarr) . ")");
2) Make sure you are actually getting a DB result, instead of just assuming:
if(!$result || mysqli_num_rows($result) == 0) {
die("We didn't get any results from the DB!"); // Obviously you'll want better error handling
}
3) Now you can open your file, knowing that you need it. Make sure to verify it worked, since you could easily hit a permissions issue:
$fp = fopen('../csv/ResultsFile_'.$ts.'.csv', 'w');
if(!$fp) {
die("We couldn't open the CSV file for writing, check permissions!"); // Obviously you'll want better error handling
}
4) Now loop through your DB results and store them:
while ($row = mysqli_fetch_array($result)) {
fputcsv($fp, $row);
}
5) Does your CSV file need a header row? If so change mysqli_fetch_array() to mysqli_fetch_assoc() and stick this inside your loop:
while ($row = mysqli_fetch_assoc($result)) {
if(!isset($header)) {
$header = array_keys($row);
fputcsv($fp, $header);
}
fputcsv($fp, $row);
}
6) Only now should you close your file (in your code you do it inside the foreach loop):
fclose($fp);
7) Sanitize your $payarr. It could be as simple as:
$payarr = is_array($_POST['pay']) ? array_map('intval', $_POST['pay']) : array();
You may want to do more than that. But at least you're guaranteed to have an array with only integer values (and as long as you have no claim_id values of 0, it's harmless to have zeros in the array).
Hope that helps, at least track down where your code is failing.

Categories