web-dev-qa-db-fra.com

exporter la fonctionnalité CSV dans mon plugin

Je dois créer une fonctionnalité "export en tant que .csv" dans mon plugin. Le problème est: je reçois un avertissement sur l'en-tête déjà envoyé, car au moment où ma fonction "export" est appelée, Wordpress a déjà commencé le rendu.

La manière dont je l'ai configurée est via un petit formulaire dans l'écran Paramètres, attribut action pointant sur un fichier (download.csv.php) de mon dossier de plug-ins, qui ne doit pas être affiché. Demander simplement une boîte de dialogue de téléchargement de fichier pour le fichier csv. déverser.

Voici mon code.

Dans l'écran de configuration de mon plugin:

<form method="post" id="download_form"  action="<?php echo plugins_url( 'download.csv.php' , __FILE__ ); ?>">
            <input type="hidden" name="download" value="<?php echo get_home_path(); ?>" />
            <input type="submit" name="download_csv"  class="button-primary" value="<?php _e('Download the log (.csv)', $this->localizationDomain); ?>" />
        </form>

Et le fichier download.csv.php:

$core = $_POST['download'].'wp-load.php';

if(isset($_POST['download']) && is_file($core)){

    require_once( $core );

    global $wpdb;

    $rows = $wpdb->get_results('SELECT * FROM `'.$this->dbName.'`;',ARRAY_A);

    if($rows){

        require_once('classes/csvmaker.class.php');
        $CSV = new CSVMaker();

        $CSVHeader = array();
        $CSVHeader['id'] = "ID";
        $CSVHeader['when'] = "WHEN";
        $CSVHeader['who'] = "WHO";
        $CSVHeader['description'] = "DESCRIPTION";
        $CSVHeader['type'] = "TYPE";

        foreach($rows as $r){
            $CSV->addEntry($r);
        }
        $file_name = plugin_dir_path(__FILE__).'data.csv';
        file_put_contents($file_name,$CSV->buildDoc);
        ob_start();
        header("Expires: Mon, 1 Apr 1974 05:00:00 GMT");
        header("Last-Modified: " . gmdate("D,d M YH:i:s") . " GMT");
        header("Cache-Control: no-cache, must-revalidate");
        header("Pragma: no-cache");
        header("Content-type: application/CSV");
        header("Content-Disposition: attachment; filename=$file_name.csv");
        echo $CSV->buildDoc;
        return ob_get_clean();
        exit;

    } 

Qu'est-ce que je fais mal?

1
pixeline

Le début de ce que vous faites mal peut s’expliquer par cette citation:

quel attribut d'action pointe vers un fichier (download.csv.php) de mon dossier de plug-ins, qui ne devrait pas être affiché; demandez simplement une boîte de dialogue de téléchargement de fichier pour le cliché csv.

et ce code:

$core = $_POST['download'].'wp-load.php';
if(isset($_POST['download']) && is_file($core)){
    require_once( $core );

Ce que vous faites en réalité est a) de sortir de l’environnement WordPress et d’accéder directement à une partie de votre plugin et b) puis de charger l’environnement WordPress depuis ce fichier (et de le faire dans un extrêmement manière peu sûre, pourrais-je ajouter).

Au lieu de cela, il est préférable de commencer par rester dans l'environnement WordPress et de remplacer le résultat comme vous le souhaitez.

Un meilleur moyen serait de rester dans l’administrateur, d’accrocher à admin_init et de détecter le moment où vous devez récupérer votre sortie CSV et la renvoyer à la place.

Donc, pour votre formulaire, faites quelque chose comme ça:

<form method="post" id="download_form" action="">
            <input type="submit" name="download_csv" class="button-primary" value="<?php _e('Download the log (.csv)', $this->localizationDomain); ?>" />
    </form>

Notez qu'aucune action n'est utilisée ici. Cela signifie qu'il est soumis à votre même page d'administrateur, sans modification. Maintenant, vous pouvez détecter cela dans n'importe quelle fonction que vous avez connectée au hook d'action admin_init, comme ceci:

global $plugin_page;
if ( isset($_POST['download_csv']) && $plugin_page == 'whatever' ) {
    echo "HELLO"; die;
}

La $ plugin_page global sera définie sur la page = tout ce que vous avez dans l'écran des paramètres de votre plugin. Au lieu de faire écho à "BONJOUR" comme je l'ai fait ici, appelez une fonction dans votre plug-in pour générer et sortir correctement ce fichier CSV, les en-têtes et tous, puis mourir. Ou quelque chose à cet effet.

Notez que ceci est simpliste et peut être peu sûr. Vous voudrez peut-être aussi faire un nonce et une vérification des capacités ici, pour vous assurer que l'utilisateur est autorisé à télécharger ce fichier CSV et dans le but de le faire.

3
Otto

Mettre tout le code mis à jour.

Dans votre mise à jour de plugin

<form method="post" id="download_form" action="">

<input type="submit" name="download_csv" class="button-primary" value="<?php _e('Download the log (.csv)', $this->localizationDomain); ?>" />

</form>

Maintenant dans votre function.php

add_action("admin_init", "download_csv");

function download_csv() {

  if (isset($_POST['download_csv'])) {

    global $wpdb;

    $sql = "SELECT * FROM {$wpdb->prefix}table_name";

    $rows = $wpdb->get_results($sql, 'ARRAY_A');

    if ($rows) {

        $csv_fields = array();
        $csv_fields[] = "first_column";
        $csv_fields[] = 'second_column';

        $output_filename = 'file_name' .'.csv';
        $output_handle = @fopen('php://output', 'w');

        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Content-Description: File Transfer');
        header('Content-type: text/csv');
        header('Content-Disposition: attachment; filename=' . 
        $output_filename);
        header('Expires: 0');
        header('Pragma: public');

        $first = true;
       // Parse results to csv format
        foreach ($rows as $row) {

       // Add table headers
            if ($first) {

               $titles = array();

                foreach ($row as $key => $val) {

                    $titles[] = $key;

                }

                fputcsv($output_handle, $titles);

                $first = false;
            }

            $leadArray = (array) $row; // Cast the Object to an array
            // Add row to file
            fputcsv($output_handle, $leadArray);
        }

        //echo '<a href="'.$output_handle.'">test</a>';

        // Close output file stream
        fclose($output_handle);

        die();
    }
  }
}
3
Aafaq Ahmad