问题描述
我想添加一个 「点击下载」 按钮到我的一个 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
文件或 include
在 functions.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 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。