任何需要用户输入(诸如改变一个变量)的插件,都需要某种管理面板。建立一个管理面板,并不是那么难的,所以,一个插件作者决定不创建管理面板,而是让用户自己去修改PHP 代码的行为让我很是苦恼。让一个用户去修改代码通常来说不是一个好主意。本文将深入探讨成功地为你的插件创建管理面板,到底需要些什么。

存储变量的地方
当你想要给你的插件创建一个管理面板的时候,你首先会碰到的问题之一就是到底在哪里存储变量值。非常幸运,WordPress 通过options 使得这件事变得非常容易。我将会在后续的系列文章中解释options 和数据库存储。现在来说,所有你需要做的事情就是点点你的头,然后跟着我的指导,把你自己的管理变量存储到WordPress 数据库中。

通常我考虑到options 的时候做的第一件事情就是,给我的管理options 取一个独特的名字。我把这个名字以成员变量的形式存储在我的类中。在这个Devlounge Plugin Series 插件的例子中,我把这个变量声明添加到DevloungePluginSerieDevloungePluginSeries
类中。

命名你的管理Options


class DevloungePluginSeries {
     var $adminOptionsName = "DevloungePluginSeriesAdminOptions";
     function DevloungePluginSeries() { //constructor }
}

第2 行显示了我存储我的成员变量的地方。我将我的变量命名为adminOptionsName并且给予它一个很长而且独特的值DevloungePluginSeriesAdminOptions。

给你的管理Options设定缺省值
你需要一个地方来初始化你的管理选项,尤其是当一个用户第一次激活你的插件的时候。然而,你还必须包正这些options 在升级中是安全的,以防万一你决定将来添加更多的options。我使用的技巧是,提供一个专门的函数来调用你的管理options。

你的插件的需求可能不一样,但是绝大多数的管理面板不会难以置信地复杂,所以一个函数对你的管理options 来说,已经足够了。

下面这个函数是我插入到类DevloungePluginSeries 中的:


//Returns an array of admin options
function getAdminOptions() {
    $devloungeAdminOptions = array('show_header' => 'true',
    'add_content' => 'true',
    'comment_author' => 'true',
    'content' => '');
    $devOptions = get_option($this->adminOptionsName);
    if (!empty($devOptions)) {
        foreach ($devOptions as $key => $option)
        $devloungeAdminOptions[$key] = $option;
    }
    update_option($this->adminOptionsName, $devloungeAdminOptions);
    return $devloungeAdminOptions;
}

这个函数做的事情是:

给你的管理options 赋默认值(3-6 行)
尝试从数据库中找出以前存储过的值(第7 行)
如果options 曾经存储过,那么存储的值会覆盖默认值(8-11 行)
options 被存储到WordPress 数据库中(第12 行)
options 被返回供你使用(第13 行)
初始化管理Options
getAdminOptions 函数可以在任何时候调用来获得管理options。然而,当插件第一次安装的时候呢?应该有某个函数被调用也能获得管理options。我在DevloungePluginSeries 类中添加了这个函数:


function init() {
    $this->getAdminOptions();
}

短小简单。但是必须有一个action 来调用这个函数


add_action('activate_devlounge-plugin-series/devlounge-plugin-series.php', array(&$dl_pluginSeries, 'init'));

这个action 有些复杂,但是很容易理清楚。下面是这个action 做的事情:

当一个插件被激活的时候你告诉它运行
你给它主要的插件PHP 文件,就是devlounge-plugin-series/devlounge-plugin-series.php。这当然是假设你把插件放到了wp-content/plugins /目录中。
你传递了一个引用给实例变量dl_pluginSeries 并且调用了init 函数。
所以,任何时候插件被激活,init 函数都会被调用。

管理面板怎样工作
在我深入到创建实际的管理面板的代码的时候,描述一下管理面板的行为是有好处的。这里有一些你设定你管理面板的步骤:

检查任何表单数据是否已经被提交。
如果表单数据存在,输出提醒。
显示管理面板Options。
在管理面板中,一个非常困扰你的问题可能是_e 的使用。_e 函数允许WordPress 搜索你文本的本地化版本。这将帮助WordPress 在将来翻译你的插件。这个函数的工作类似一个普通的echo,但是你传给它的是你的文本和一个标识变量(典型的是你的插件名称)。一个例子:

_e('Update Settings','DevloungePluginSeries');
这句代码和:

echo "Update Settings";
是相同的。

设置你的管理面板函数
我们想要做的第一件事情就是设定一个函数,来真正地打印出一个管理面板。函数名字叫做printAdminPage。下一段代码将要读入我们早先设定的options 并且检查是否所有的发布options 已经被提交。这一段的所有代码假设写在printAdminPage函数中。


//Prints out the admin page
function printAdminPage() {
$devOptions = $this->getAdminOptions();
if (isset($_POST['update_devloungePluginSeriesSettings'])) {
    if (isset($_POST['devloungeHeader'])) {
        $devOptions['show_header'] = $_POST['devloungeHeader'];
    }
    if (isset($_POST['devloungeAddContent'])) {
        $devOptions['add_content'] = $_POST['devloungeAddContent'];
    }
    if (isset($_POST['devloungeAuthor'])) {
        $devOptions['comment_author'] = $_POST['devloungeAuthor'];
    }
    if (isset($_POST['devloungeContent'])) {
        $devOptions['content'] = apply_filters('content_save_pre',
        $_POST['devloungeContent']);
    }
    update_option($this->adminOptionsName, $devOptions);
    ?>
    <div class="updated"><p><strong><?php _e("Settings Updated.",
    "DevloungePluginSeries");?></strong></p></div>
    <?php
}

上面所有代码做的是装载options 并且测试是否表单的每个部分都已经被正确提交。if 语句并不是必须的,但是有的时候对于调试来说很有用。第一被测试的表单变量是update_devloungePluginSeriesSettings。这个变量被赋值给我们的“提交”按钮。

如果它没有被设定,那么说明这个表单没有被提交。

就像说好的一样,在第16 行,我使用了apply_filters 函数来格式化内容,以便存入数据库。

下一段代码将会显示一个HTML 表单,那是管理面板锁必须的。它有一些复杂,所以我会这里概括一下。所有的代码做的事情,就是显示表单元素和读入options。


<div class=wrap>
<form method="post" action="<?php echo $_SERVER["REQUEST_URI"]; ?>">
<h2>Devlounge Plugin Series</h2>
<h3>Content to Add to the End of a Post</h3>
<textarea name="devloungeContent" style="width: 80%; height: 100px;"><?php _e(apply_filters
('format_to_edit',$devOptions['content']), 'DevloungePluginSeries') ?></textarea>
<h3>Allow Comment Code in the Header?</h3>
<p>Selecting "No" will disable the comment code inserted in the header.</p>
<p><label for="devloungeHeader_yes"><input type="radio" id="devloungeHeader_yes"
name="devloungeHeader" value="true" <?php if ($devOptions['show_header'] == "true")
{ _e('checked="checked"', "DevloungePluginSeries"); }?> /> Yes</label> <label
for="devloungeHeader_no"><input type="radio" id="devloungeHeader_no"
name="devloungeHeader" value="false" <?php if ($devOptions['show_header'] == "false")
{ _e('checked="checked"', "DevloungePluginSeries"); }?>/> No</label></p>
<h3>Allow Content Added to the End of a Post?</h3>
<p>Selecting "No" will disable the content from being added into the end of a post.</p>
<p><label for="devloungeAddContent_yes"><input type="radio" id="devloungeAddContent_yes"
name="devloungeAddContent" value="true" <?php if ($devOptions['add_content'] == "true")
{ _e('checked="checked"', "DevloungePluginSeries"); }?> /> Yes</label> <label
for="devloungeAddContent_no"><input type="radio" id="devloungeAddContent_no"
name="devloungeAddContent" value="false" <?php if ($devOptions['add_content'] == "false")
{ _e('checked="checked"', "DevloungePluginSeries"); }?>/> No</label></p>
<h3>Allow Comment Authors to be Uppercase?</h3>
<p>Selecting "No" will leave the comment authors alone.</p>
<p><label for="devloungeAuthor_yes"><input type="radio" id="devloungeAuthor_yes"
name="devloungeAuthor" value="true" <?php if ($devOptions['comment_author'] == "true")
{ _e('checked="checked"', "DevloungePluginSeries"); }?> /> Yes</label> <label
for="devloungeAuthor_no"><input type="radio" id="devloungeAuthor_no"
name="devloungeAuthor" value="false" <?php if ($devOptions['comment_author'] == "false")
{ _e('checked="checked"', "DevloungePluginSeries"); }?>/> No</label></p>
<div class="submit">
<input type="submit" name="update_devloungePluginSeriesSettings" value="<?php _e('Update
Settings', 'DevloungePluginSeries') ?>" /></div>
</form>
</div>
<?php
}//End function printAdminPage()

需要在上述代码中观察的是options 的引用,和HTML 和PHP 是怎样集成的。

设置管理面板Action现在,printAdminPage 函数已经添加了,我们需要通过一个action 调用它。首先函数必须被设定在正好在action 的上面,在类的范围之外。


//Initialize the admin panel
if (!function_exists("DevloungePluginSeries_ap")) {
    function DevloungePluginSeries_ap() {
        global $dl_pluginSeries;
        if (!isset($dl_pluginSeries)) {
            return;
        }
        if (function_exists('add_options_page')) {
            add_options_page('Devlounge Plugin Series', 'Devlounge Plugin Series', 9,
            basename(__FILE__), array(&$dl_pluginSeries, 'printAdminPage'));
        }
    }
}

上面的代码做了下面这些事:

创建了一个叫做DevloungePluginSeries_ap 的函数。
测试变量dl_pluginSeries 是否存在(4-7 行)。这个变量是我们的类的引用。
一个叫做“Devlounge Plugin Series”的管理页面被初始化了,并且,我们的printAdminPage 函数被引用了。(8-10 行)。
add_options_page 函数的调用方法为:

add_options_page(page_title,menu_title,access_level/capability,file,[function]);
访问级别(在这个例子中是9)在WordPress Codex 的Users Levels page 页面有详细的描述。

必须设置一个action 来调用DevloungePluginSeries_ap 函数:

add_action('admin_menu', 'DevloungePluginSeries_ap');