I have to run a pairing algorithm for a game and when the pairing is done, I display the pairing on HTML and create a csv file as well. Right now, once I am done with pairing, I create a multidimensional array to store the specific value and then pass it to the function in same php file to generate the csv file. However, doing this outputs the entire page code i.e. html and php code to the .csv file. Here is the code:
function performPairing()
{
....
$count=0;
$resultArray[][] = array();
while ($currrow = #mysql_fetch_row($result))
{
$playerone = $currrow;
$playertwo = #mysql_fetch_row($result);
$resultArray[$count][] = $playerone[1];
$resultArray[$count][] = $playerone[0];
$resultArray[$count][] = $playertwo[1];
$resultArray[$count][] = $playertwo[0];
$count++;
updateforeachrow($playerone, $playertwo);
}
generateDocument($resultArray, $count);
}
function generateDocument($resultArray, $count)
{
$output = fopen('php://temp/maxmemory'.(5*1024*1024), 'r+');
$columns = array('Player One Col1', 'Player One Col2', 'Player Two Col1', 'Player Two Col2');
fputcsv($output, $columns);
for ($index=0 ; $index <=$count; $index++)
{
fputcsv($output, $resultArray[$index]);
}
rewind($output);
$export = stream_get_contents($output);
fclose($output);
header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename = "export.csv"');
echo $export;
}
However doing this outputs the entire html code to csv rather than specific rows. Can anyone please help me on this?
. make string
. output string to file
. send header with (is this allowed this way?)
use file_put_contents ( filename, str ), and than send it with headers.
Make code simpler :)
Related
I have console app made in Symfony3, where user can import CSV file (which is validate) into database. I need to put records which haven't passed validation into separate file.
I use LeagueCSV to read CSV file and I try to use it to write unvalidated records but it doesn't work.
This is my code:
$reader = Reader::createFromPath($input->getArgument('lokalizacja'));
$reader->setDelimiter(';');
$reader->setHeaderOffset(0);
$results = $reader->getRecords();
foreach ($results as $row) {
$year = $row['description'];
$isValid = false;
if ($row['qty'] > 0 && $row['price'] > 0 && !empty($row['mpn'])) {
$isValid = true;
$rok = filter_var($row['description'], FILTER_SANITIZE_NUMBER_INT);
$product = (new Produkt())
->setMpn($row['mpn'])
->setQty($row['qty'])
->setYear($year)
->setPrice($row['price']);
$this->em->persist($product); }
if ($row['qty'] == 0 || $row['price'] == 0 || empty($row['mpn'])) {
$writer = Writer::createFromPath('/path/to/saved/file.csv', 'w+');
$writer->insertOne([$row['mpn'], $row['qty'], $row['price'],
$row['description']]);
continue;
}
}
$this->em->flush();
All records which passed validation are successfully saved in the database but I have problem with others records. In new CSV file I have only first, one record which haven't passed validation and nothing more. What am I doing wrong? I tried with
$writer->insertAll($results); //using an array
Or with if...else statment but that's nothing.
Also I made ...else statement where unvalidated records are saved in other table in database and its works but I don't know how to immediately convert them into CSV file.
Don't know symfony but CSV output is pretty simple. FWIW...
Pass this an array, like a fetchall resultset.
<?php
public function outputCSV($data, $useKeysForHeaderRow = true) {
if ($useKeysForHeaderRow) {
array_unshift($data, array_keys(reset($data)));
}
$outputBuffer = fopen("php://output", 'w');
foreach($data as $v) {
fputcsv($outputBuffer, $v);
}
fclose($outputBuffer);
}
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="FooBarFileName_' . date('Ymd') . '.csv"');
header("Pragma: no-cache");
header("Expires: 0");
$this->outputCSV($results);
If you look at the doc page for the writer you will see a warning at the top which states
When inserting records into a CSV document using League\Csv\Writer, first insert all the data that need to be inserted before starting manipulating the CSV. If you manipulate your CSV document before insertion, you may change the file cursor position and erase your data.
Your code calls
$writer = Writer::createFromPath('/path/to/saved/file.csv', 'w+');
$writer->insertOne([$row['mpn'], $row['qty'], $row['price'], $row['description']]);
In every iteration the condition is met, this appears to be overwriting or dropping your previous insert every time. You should declare the $writer once before the loop starts in order to preserve each insert.
$writer = Writer::createFromPath('/path/to/saved/file.csv', 'w+');
foreach ($results as $row) {
// do stuff with $writer
}
Following is a part of my php program which is written to fetch rows from mysql table from input IDs. But I wanted to get the result directly to '.csv' file. I know php has built in function for that, but I could not include it effectively. So can anyone give a direction for export to csv using advanced php function?
$file = fopen("fetched.csv","w");
for($i=0;$i<=$len;$i++)
{
$lo = $locus[$i];
mysqli_select_db($conn,"microarray");
$query = mysqli_query("SELECT * FROM anatomy WHERE locus_id = "$lo"");
while ($row = mysqli_fetch_row($query))
{
}
}
You don't necessarily need an "advanced php function". A csv file is just a sequence of comma separated columns. Try this out.
function addRowToCsv(& $csvString, $cols) {
$csvString = implode(',', $cols) . PHP_EOL;
}
$csvString = '';
$first = true;
while ($row = mysqli_fetch_assoc($query)) {
if ($first === true) {
$first = false;
addRowToCsv($csvString, array_keys($row));
}
addRowToCsv($csvString, $row);
}
header('Content-type: text/csv');
header('Content-disposition: attachment;filename=MyCsvFile.csv');
echo $csvString;
Notice that the first argument to addRowToCsv is passed by reference. This is not required and you could easily use a return value, but this is just how I would do it.
-- Edit --
I just noticed you are saving the output to a file rather than serving it as a download. If that is what you want to do then use the above but replace
header('Content-type: text/csv');
header('Content-disposition: attachment;filename=MyCsvFile.csv');
echo $csvString;
With..
file_put_contents('MyCsvFile.csv', $csvString);
I don't have a lot of experience with using the fputcsv function.
I'm trying to make a function, by which an admin can download a file with all the user information.
The CSV should be generated in this way :
Serial Number Username Email etc etc
And then the records from a query.
I have this function which I'm using to generate the csv file :
function array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
// open raw memory as file so no temp files needed, you might run out of memory though
$f = fopen('php://memory', 'w');
// loop over the input array
foreach ($array as $line) {
// generate csv lines from the inner arrays
fputcsv($f, $line, $delimiter);
}
// rewrind the "file" with the csv lines
fseek($f, 0);
// tell the browser it's going to be a csv file
header('Content-Type: application/csv');
// tell the browser we want to save it instead of displaying it
header('Content-Disposition: attachement; filename="'.$filename.'";');
// make php send the generated csv lines to the browser
fpassthru($f);
}
And then I call the function:
<?php
include 'inc/inc.functions.php';
include 'dbconnector.php';
$query="SELECT * from users order by email LIMIT 0,30";
$result=mysql_query($query,$db) or die(mysql_error($db));
$array=mysql_fetch_array($result);
foreach($array as $arr)
{
array_to_csv_download($arr,"records.csv",":");
}
?>
The CSV generated displays: Warning, Invalid argument supplied for foreach.
What should I do to display in the way I require?
UPDATE
http://i.imgur.com/2xH0gT1.png
You're currently calling your function for a single row in the database, rather than for the entire result set. The following should use your function correctly:
$query = "SELECT * from users order by email LIMIT 0,30";
$result = mysql_query($query,$db) or die(mysql_error($db));
$array = array();
# Headers
$array[] = array("Serial Number","Username","Email","etc etc");
while($row = mysql_fetch_row($result)) {
$array[] = $row;
}
array_to_csv_download($array,"records.csv",":");
I'm trying to generate a CSV file on the fly, depending on what the user selects as report output. Retrieving the data and writing it to a file using CakeResponse is done, however I'm struggling to set the file extension to '.csv', the file get downloaded as a normal text file.
CakePHP documentation suggests I do this:
$this->response->type('csv');
..but even this is not working, I'm still getting a text file. Can anyone shed some light? Please note, I'm not looking for new methods to generate a CSV file, I just want to change the extension. Thank you.
This is how I download the file:
$this->response->body($this->constructFileBody($logs));
return $this->response;
This is the method 'constructFileBody', although I think its beyond the scope of this question:
public function constructFileBody($logs = array()){
$content = "";
for($i = 0; $i < count($logs); $i++){
$row = $logs[$i]['EventLog'];
$line = $row['description'] . "," . $row['user'] . "," . $row['affected_user'] . "," . $row['report_title'] . "," . $row['date_created'] . "\n";
$content = $content . $line;
}
return $content;
}
As i saw your code, I don't think you used the header anywhere, try this code:
//create a file
$filename = "export_".date("Y.m.d").".csv";
$csv_file = fopen('php://output', 'w');
header('Content-type: application/csv');
header('Content-Disposition: attachment; filename="'.$filename.'"');
$results = $this->ModelName->query($sql); // This is your sql query to pull that data you need exported
//or
$results = $this->ModelName->find('all', array());
// The column headings of your .csv file
$header_row = array("ID", "Received", "Status", "Content", "Name", "Email", "Source", "Created");//columns you want in csv file
fputcsv($csv_file,$header_row,',','"');
// Each iteration of this while loop will be a row in your .csv file where each field corresponds to the heading of the column
foreach($results as $result)
{
// Array indexes correspond to the field names in your db table(s)
$row = array(
$result['ModelName']['id'],
$result['ModelName']['received'],
$result['ModelName']['status'],
$result['ModelName']['content'],
$result['ModelName']['name'],
$result['ModelName']['email'],
$result['ModelName']['source'],
$result['ModelName']['created']
);
fputcsv($csv_file,$row,',','"');
}
fclose($csv_file);
Now look at your code and get the line of code mine which needs to be replaced.
I want to download a .csv file through link.For that a Download link is defined in a template file.
To generate .csv file I have written a piece of code as follows.
public function loadPartnerApplicantData() {
$inboundBo = BoFactory::getInboundHttpRequestBo();
$fileType = $inboundBo->getSanitizedGetParam('f');
$formId = $inboundBo->getSanitizedGetParam('fid');
ServiceFactory::getFormService()->loadFormDetails($formId);
$dbTable = BoFactory::getFormBo()->getFormDbTable($formId);
$formName = slugify(BoFactory::getFormBo()->getFormName());
$fileName = $formName . "." . time();
$fieldMasterSqlQuery = "SELECT field_name,field_label FROM" . FORM_FIELDS_MASTER_v2 . "where form_id='$formId' order by serial_no";
$fieldMasterSqlQueryStatus = mysql_query(mysql_fetch_assoc($fieldMasterSqlQuery));
$csvHeader = "";
$fieldNameArray = array();
foreach ($fieldMasterSqlQueryStatus as $key => $value) {
if ($value['field_name'] == 'declaration' || $value['field_name'] == 'docPicture') {
continue;
}
$csvHeader.= "\"{$value['field_label']}\";";
$fieldNameArray[] = $value['field_name'];
}
$queryString = implode(",", $fieldNameArray);
$dbTableSqlQuery = "SELECT $queryString FROM `$dbTable`";
$dbTableSqlQueryStaus = mysql_query(mysql_fetch_assoc($dbTableSqlQuery));
ef_clearBuffer();
// To generate csv
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=$fileName.csv");
header("Pragma: no-cache");
header("Expires: 0");
echo($csvHeader);
foreach ($dbTableSqlQueryStaus as $applicantData) {
echo "\n";
foreach ($fieldNameArray as $fieldName) {
echo "\"$applicantData[$fieldName]\";";
}
echo "\n";
}
}
And the required .csv is generated .
But at the end of .csv file HTML tags of the browser is getting displayed. which should not be there.
Please suggest me to remove the html content from the generated .csv file.
Thanks in advance.
Since your function handles the request till the end (i.e., delivers all data), and you don't want the framework (whichever you're using) to continue processing, add
exit(0);
as last line of your function. That will halt the processing after the content is delivered and prevent the framework/environment from sending additional data.
Maybe you already had some echo commands before the header manipulation, then the .csv file which you want to download will contains all strings you have written before.