問題描述

我想新增一個 「點選下載」 按鈕到我的一個 WordPress 外掛,我不知道使用哪個鉤子。到目前為止,將’admin_init’ 掛接到此程式碼似乎工作:

 header("Content-type: application/x-msdownload");
 header("Content-Disposition: attachment; filename=data.csv");
 header("Pragma: no-cache");
 header("Expires: 0");
 echo 'data';
 exit();

這似乎是有效的,但我只想看看是否有最佳實踐。

謝謝,戴夫

最佳解決方案

如果我正確理解您的意圖,您希望擁有一個如下所示的 URL,那麼對瀏覽器的響應將是您生成的內容,即您的.CSV 檔案,並且沒有從 WordPress 生成的內容?

http://example.com/download/data.csv

我想你正在尋找'template_redirect'鉤。您可以在/wp-includes/template-loader.php 中找到'template_redirect',這是所有 WordPress 開發人員應該熟悉的檔案; 它是短暫和甜蜜,路線每一個 non-admin 頁面載入,所以一定要看看它。

只需將以下內容新增到主題的 functions.php 檔案或 includefunctions.php 中的另一個檔案中即可:

add_action('template_redirect','yoursite_template_redirect');
function yoursite_template_redirect() {
  if ($_SERVER['REQUEST_URI']=='/downloads/data.csv') {
    header("Content-type: application/x-msdownload",true,200);
    header("Content-Disposition: attachment; filename=data.csv");
    header("Pragma: no-cache");
    header("Expires: 0");
    echo 'data';
    exit();
  }
}

透過檢查 $_SERVER['REQUEST_URI']來注意'/downloads/data.csv' URL 的測試。另請注意新增,true,200 到您的 header()呼叫,您設定 Content-type; 這是因為 WordPress 會設定 404 “Not Found” 狀態程式碼,因為它不能識別該 URL 。這是沒有問題的,因為 true 告訴 header()替換 404 WordPress 已經設定並使用 HTTP 200 “Okay” 狀態程式碼。

FireFox 這是什麼樣子 (請注意,螢幕截圖沒有/downloads/虛擬目錄,因為在拍攝和註釋螢幕截圖後,似乎最好新增一個'/downloads/'虛擬目錄):

UPDATE

如果您希望從一個字首為/wp-admin/的 URL 處理下載,以向使用者提供受到登入保護的可視指示,那麼您也可以這樣做:下面描述一種方法。

這次我封裝成一個類,稱為 DownloadCSV,併為 「管理員」 角色建立了一個名為 「download_csv」 的使用者 「功能」(請閱讀此處的角色和功能) 您可以搭載預定義的 「匯出」 角色,如果你喜歡,如果是這樣搜尋& 用’export’ 替換’download_csv’,並刪除 register_activation_hook() 呼叫和 activate() 函式。順便說一句,需要一個啟用鉤子是我把這個移植到外掛而不是保留在主題的 functions.php 檔案中的一個原因。*

我還使用 add_submenu_page()從”Tools” 選單中新增了”Download CSV” 選單選項,並將其連結到'download_csv'功能。

最後我選擇了'plugins_loaded'鉤子,因為它是我可以使用的最早的適當鉤子。你可以使用'admin_init',但這個鉤子執行得比較晚 (第 1130 次鉤子呼叫和第 3 個鉤子呼叫),所以為什麼讓 WordPress 做更多的 throw-away 工作呢? (我用我的 Instrument Hooks plugin 找出要使用的鉤子。)

在鉤子中,我檢查以確保我的 URL 從/wp-admin/tools.php 透過檢查 $ pagenow 變數開始,我驗證 current_user_can(‘download_csv’),如果透過,我測試 $ _GET [‘download’] 看它是否包含資料。 CSV; 如果是,我們幾乎執行與之前相同的程式碼。我也刪除了前面的例子中的來自 header() 的 200 的 true,因為這裡 WordPress 知道這是一個很好的 URL,所以沒有設定 404 狀態。所以這裡是你的程式碼:

<?php
/*
Plugin Name: Download CSV
Author: Mike Schinkel
Author URI: http://mikeschinkel.com
 */
if (!class_exists('DownloadCSV')) {
  class DownloadCSV {
    static function on_load() {
      add_action('plugins_loaded',array(__CLASS__,'plugins_loaded'));
      add_action('admin_menu',array(__CLASS__,'admin_menu'));
      register_activation_hook(__FILE__,array(__CLASS__,'activate'));
    }
    static function activate() {
      $role = get_role('administrator');
      $role->add_cap('download_csv');
    }
    static function admin_menu() {
      add_submenu_page('tools.php',    // Parent Menu
        'Download CSV',                // Page Title
        'Download CSV',                // Menu Option Label
        'download_csv',                // Capability
        'tools.php?download=data.csv');// Option URL relative to /wp-admin/
    }
    static function plugins_loaded() {
      global $pagenow;
      if ($pagenow=='tools.php' && 
          current_user_can('download_csv') && 
          isset($_GET['download'])  && 
          $_GET['download']=='data.csv') {
        header("Content-type: application/x-msdownload");
        header("Content-Disposition: attachment; filename=data.csv");
        header("Pragma: no-cache");
        header("Expires: 0");
        echo 'data';
        exit();
      }
    }
  }
  DownloadCSV::on_load();
}

這裡是啟用的外掛的螢幕截圖:

最後這是一個觸發下載的螢幕截圖:

次佳解決方案

一個更有用的外掛,用於匯出到 CSV 。可能對某些人有用

    <?php

class CSVExport
{
/**
* Constructor
*/
public function __construct()
{
if(isset($_GET['download_report']))
{
$csv = $this->generate_csv();

header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename="report.csv";" );
header("Content-Transfer-Encoding: binary");

echo $csv;
exit;
}

// Add extra menu items for admins
add_action('admin_menu', array($this, 'admin_menu'));

// Create end-points
add_filter('query_vars', array($this, 'query_vars'));
add_action('parse_request', array($this, 'parse_request'));
}

/**
* Add extra menu items for admins
*/
public function admin_menu()
{
add_menu_page('Download Report', 'Download Report', 'manage_options', 'download_report', array($this, 'download_report'));
}

/**
* Allow for custom query variables
*/
public function query_vars($query_vars)
{
$query_vars[] = 'download_report';
return $query_vars;
}

/**
* Parse the request
*/
public function parse_request(&$wp)
{
if(array_key_exists('download_report', $wp->query_vars))
{
$this->download_report();
exit;
}
}

/**
* Download report
*/
public function download_report()
{
echo '<div class="wrap">';
echo '<div id="icon-tools" class="icon32">
</div>';
echo '<h2>Download Report</h2>';
//$url = site_url();

echo '<p>Export the Users';
}

/**
* Converting data to CSV
*/
public function generate_csv()
{
$csv_output = '';
$table = 'users';

$result = mysql_query("SHOW COLUMNS FROM ".$table."");

$i = 0;
if (mysql_num_rows($result) > 0) {
while ($row = mysql_fetch_assoc($result)) {
$csv_output = $csv_output . $row['Field'].",";
$i++;
}
}
$csv_output .= "n";

$values = mysql_query("SELECT * FROM ".$table."");
while ($rowr = mysql_fetch_row($values)) {
for ($j=0;$j<$i;$j++) {
$csv_output .= $rowr[$j].",";
}
$csv_output .= "n";
}

return $csv_output;
}
}

// Instantiate a singleton of this plugin
$csvExport = new CSVExport();

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。