admin管理员组

文章数量:1302584

I have some code, implemented by a shortcode within a custom plugin. The code generates a CSV file from some data tables. When I run the shortcode within the admin section, it works perfectly. BUT when I attempt to run it on the front end, it fills the top of the CSV file with the pages HTML data such as:

<?DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
.......

#  ID    Product      Price
1   2a   keys        10.00
2   2b   doors       55.00

The table of data does export, as it did in the admin section of the plugin. Just when the shortcode to the function is placed on the front end, the results is HTML code at the top of the file (as seen above). Can not for the life of me figure out how to stop this. The goal is to be able to have the user output, in CSV format, all their purchases. Here is the code:


function ShowResults($Name)
{
$rows = mmd_GetProducts($Name);

ob_start();
ob_end_flush();
header('Pragma: public');
header( 'Expires: 0' );
header( 'Cache-Control: private', false );
header( 'Content-Type: text/csv');
header( 'Content-Disposition: attachment; filename="'. 'Results.csv"');
$fp = fopen('php://output', 'w');

$header_row = array(
        0 => '#',
        1 => 'ID',
        2 => 'Product',
        3 => 'Price',
    );
fputcsv($fp, $header_row);

foreach($rows as $Record)
  { 
     if($Record['bDoNotDisplay'] == 1 )
        continue;
  
  $OutputRecord = array($cnt
                        $Record['id'], 
                        $Record['product'],  
                        $Record['price']);
    $cnt ++;
    fputcsv($fp, $OutputRecord);         
    }
unset($rows);

fclose( $fp );
ob_end_clean(); 
exit();
}

UPDATE BUT STILL A PROBLEM

Similar issue, except now the HTML code is at the bottom of the file. I changed the code to use add_action instead of calling a short code. I use this wordpress action call and then detect if this is the page that is loading

add_action( 'template_redirect', 'ShowResults', 10); 
function ShowResults()
{
 global $post;
 
$title = get_the_title($post); 

if($title == "Export")
   {
   OutputCSV();
   }
 }


function OutputCSV()
{
$rows = mmd_GetProducts($Name);

ob_start();
ob_end_flush();
header('Pragma: public');
header( 'Expires: 0' );
header( 'Cache-Control: private', false );
header( 'Content-Type: text/csv');
header( 'Content-Disposition: attachment; filename="'. 'Results.csv"');
$fp = fopen('php://output', 'w');

$header_row = array(
        0 => '#',
        1 => 'ID',
        2 => 'Product',
        3 => 'Price',
    );
fputcsv($fp, $header_row);

foreach($rows as $Record)
  { 
     if($Record['bDoNotDisplay'] == 1 )
        continue;
  
  $OutputRecord = array($cnt
                        $Record['id'], 
                        $Record['product'],  
                        $Record['price']);
    $cnt ++;
    fputcsv($fp, $OutputRecord);         
    }
unset($rows);

fclose( $fp );
ob_end_clean(); 
exit();

}

Now the HTML code appears at the bottom of the file and not the top. Any suggestions?

I have some code, implemented by a shortcode within a custom plugin. The code generates a CSV file from some data tables. When I run the shortcode within the admin section, it works perfectly. BUT when I attempt to run it on the front end, it fills the top of the CSV file with the pages HTML data such as:

<?DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
.......

#  ID    Product      Price
1   2a   keys        10.00
2   2b   doors       55.00

The table of data does export, as it did in the admin section of the plugin. Just when the shortcode to the function is placed on the front end, the results is HTML code at the top of the file (as seen above). Can not for the life of me figure out how to stop this. The goal is to be able to have the user output, in CSV format, all their purchases. Here is the code:


function ShowResults($Name)
{
$rows = mmd_GetProducts($Name);

ob_start();
ob_end_flush();
header('Pragma: public');
header( 'Expires: 0' );
header( 'Cache-Control: private', false );
header( 'Content-Type: text/csv');
header( 'Content-Disposition: attachment; filename="'. 'Results.csv"');
$fp = fopen('php://output', 'w');

$header_row = array(
        0 => '#',
        1 => 'ID',
        2 => 'Product',
        3 => 'Price',
    );
fputcsv($fp, $header_row);

foreach($rows as $Record)
  { 
     if($Record['bDoNotDisplay'] == 1 )
        continue;
  
  $OutputRecord = array($cnt
                        $Record['id'], 
                        $Record['product'],  
                        $Record['price']);
    $cnt ++;
    fputcsv($fp, $OutputRecord);         
    }
unset($rows);

fclose( $fp );
ob_end_clean(); 
exit();
}

UPDATE BUT STILL A PROBLEM

Similar issue, except now the HTML code is at the bottom of the file. I changed the code to use add_action instead of calling a short code. I use this wordpress action call and then detect if this is the page that is loading

add_action( 'template_redirect', 'ShowResults', 10); 
function ShowResults()
{
 global $post;
 
$title = get_the_title($post); 

if($title == "Export")
   {
   OutputCSV();
   }
 }


function OutputCSV()
{
$rows = mmd_GetProducts($Name);

ob_start();
ob_end_flush();
header('Pragma: public');
header( 'Expires: 0' );
header( 'Cache-Control: private', false );
header( 'Content-Type: text/csv');
header( 'Content-Disposition: attachment; filename="'. 'Results.csv"');
$fp = fopen('php://output', 'w');

$header_row = array(
        0 => '#',
        1 => 'ID',
        2 => 'Product',
        3 => 'Price',
    );
fputcsv($fp, $header_row);

foreach($rows as $Record)
  { 
     if($Record['bDoNotDisplay'] == 1 )
        continue;
  
  $OutputRecord = array($cnt
                        $Record['id'], 
                        $Record['product'],  
                        $Record['price']);
    $cnt ++;
    fputcsv($fp, $OutputRecord);         
    }
unset($rows);

fclose( $fp );
ob_end_clean(); 
exit();

}

Now the HTML code appears at the bottom of the file and not the top. Any suggestions?

Share Improve this question edited Mar 3, 2021 at 17:53 Debbie Kurth asked Mar 1, 2021 at 19:41 Debbie KurthDebbie Kurth 4323 silver badges14 bronze badges 6
  • Note that the shortcode's output must be returned by the callback and the page headers are already sent when the shortcode is rendered in the post content. – birgire Commented Mar 2, 2021 at 9:01
  • birgire...what would you suggest? – Debbie Kurth Commented Mar 2, 2021 at 20:24
  • 1 to output the download link/button you can use the shortcode but for the actual csv download I think you would need to halt the flow before the theme's output, e.g. earlier or same as the template_redirect hook – birgire Commented Mar 3, 2021 at 15:48
  • Ironic...that is EXACTLY what I started working with late yesterday. Yes it works! Howeer, now I am getting the HTML after the table output and the template_redirect is called twice. Suggestions? – Debbie Kurth Commented Mar 3, 2021 at 15:53
  • hard to say what's going on there :-) but in general the shortcode callback must return the download link, not echo it. The download code itself must be outside of the shortcode and it must use some logic and exit within some early hook. best of luck. – birgire Commented Mar 3, 2021 at 15:58
 |  Show 1 more comment

1 Answer 1

Reset to default 1

Well this was a journey! The solution was 'die' and not exit AND use the add_action call that resulted in a notification PRIOR to any header call being called. The die forced the system to quit before attempting to write out the headers at the end of file.

The final code that works:

add_action( 'template_redirect', 'ShowResults', 10); 
function ShowResults($Name)
{
 global $post;
 $title = get_the_title($post);

if($title == "Export")
   OutputCSV();
}

function ExportCSV()
{
$rows = mmd_GetProducts($Name);

header('Pragma: public');
header( 'Expires: 0' );
header( 'Cache-Control: private', false );
header( 'Content-Type: text/csv');
header( 'Content-Disposition: attachment; filename="'. 'Results.csv"');
$fp = fopen('php://output', 'w');

$header_row = array(
        0 => '#',
        1 => 'ID',
        2 => 'Product',
        3 => 'Price',
    );
fputcsv($fp, $header_row);

foreach($rows as $Record)
  { 
     if($Record['bDoNotDisplay'] == 1 )
        continue;
  
  $OutputRecord = array($cnt
                        $Record['id'], 
                        $Record['product'],  
                        $Record['price']);
    $cnt ++;
    fputcsv($fp, $OutputRecord);         
    }
unset($rows);

fclose( $fp );
die;                  <<<=========== die NOT exit.
}

本文标签: databaseExporting table to csv works in the admin but exports HTML data when used on the front end