为你的wordpress主题添加选项页

准确的说,这篇主要是译作。我在搜索wordpress+主题+选项的时候并没有找到合适的教程。只有Neoease小哥的一篇符合要求。但是他把一堆属性放到表格的同一位置存放,用起来不是很方便。接着换用英文关键字,终于搜到了这个不错的教程。所以翻译一下并结合自己的理解写这一篇。
我很有诚意的!为了写这个俺甚至换了显示代码的插件。

为主题添加一个选项页是降低复杂主题管理难度的最好的方法。但是,能Google到的资料很少所以很多人都放弃了。在设计上一个如此重要的应用却有很少的文档,貌似那些资深开发者们都把这个方法当作祖传秘方私藏了起来。
在这篇文章中我将合并一个选项面板到WP默认主题(WordPress Classic)中,你学到的方法将很容易扩展到自己的工程上。

首先,blabla……(与WP无关),感谢国家。

我们的目标是,没有蛀牙
我们的目标是,在Wordpress的默认主题上方开辟一个区域,用来显示一段欢迎语。这段欢迎语的内容可以在后台的选项页中进行编辑。后台界面是这个样子的:
welcom
如果对加入的选项页的格式不加以控制的话,看起来会非常别扭,所以修改的内容中还包括一部分后台界面的美化。

****后台修改****
我们从修改/wp-content/themes/classic/下的functions.php开始。
为了避免麻烦,在functions.php文件的最前或最后加上下面的代码是最安全的。

首先添加

<?php
$themename = "WordPress Classic"; //改成你主题的名字,可以用中文
$shortname = "wpc";				//你主题名字的缩写,一定不要用中文!

$options = array (

	array(	"name" => "欢迎语",  
			"type" => "title"),
			
	array(	"type" => "open"),
	
	array(	"name" => "标题",
			"desc" => "输入欢迎语页面的标题.",
			"id" => $shortname."_welcome_title",
			"std" => "",
			"type" => "text"),
			
	array(	"name" => "内容",
			"desc" => "欢迎语的内容.",
            "id" => $shortname."_welcome_message",
            "type" => "textarea"),
	
	array(  "name" => "是否显示?",
			"desc" => "选中此项如果你**不想**显示欢迎语.",
            "id" => $shortname."_welcome_disable",
            "type" => "checkbox",
            "std" => "false"),
	//再有想添加的可以参照这个格式进行
	/*
		array(	"name" => "内容2",
				"desc" => "内容2的内容",
			            "id" => $shortname."_welcom2",
			            "type" => "textarea"),
	*/
	array(	"type" => "close")
	
);

这里是我们创建选项的地方。
我们把每个选项都放到一个数组中,方便在后面把它们组合到一起。每个选项都有一下复用的代码。在每个数组中,我们使用如下参数:
name – 用来显示这个选项的标题(可以是中文)。
desc – 对于这个选项的描述(可以是中文)。
id – 非常重要! 我们用来识别每个存储数据。 $shortname将与id组合到一起存到数据库中,所以id是不能重复的。 (在我们的例子中,把$shortname设成wpc)。
std – 选项的默认值. 例如对于checkbox类型,可以设成true或者false以决定这个选项初始的时候是否选中。
type – 用来定义选项显示的类别. 像文字、文字输入框、checkbox之类。
首先以title类型作为开始。
‘open’选项才是真正有意义的开始,作用是开始表格的绘制(是的,原作者那个笨蛋为了好看用了table,后悔来不及了已经。)
接下来用一个text做欢迎语选项的标题,之后用一个textarea来存放消息的内容。接下来的checkbox用来决定是否启用这个欢迎语。
最后用’close’跟’open’相对应。

所以,利用这个模板,你可以在open和close之间任意增加或删除选项,所要做的只是照葫芦画瓢写一个array而已。注意id。

后边的部分是一坨Wordpress代码,用来具体实现选项页的做成和功能。不感兴趣的可以跳过。感兴趣的,我也在我能看懂的部分加了中文注释。
如果特别关注的话,会发现我对原英文作者的代码改动了两处。因为原来的作者没考虑到往数据库里存代码(比如adsense或analitics)的情况。
And now for the rest of the code. Most of which is a bunch of WordPress functions to tell it this is an options page, so we wont go over most of it:

function mytheme_add_admin() {

    global $themename, $shortname, $options;

    if ( $_GET['page'] == basename(__FILE__) ) {
    
        if ( 'save' == $_REQUEST['action'] ) { //save按下时的动作

                foreach ($options as $value) {				
					//将内容更新到数据库.译者添加去转义字符命令stripslashes
                    update_option( $value['id'], stripslashes($_REQUEST[ $value['id'] ]) ); 
					}

                foreach ($options as $value) {
                    if( isset( $_REQUEST[ $value['id'] ] ) ) {
						//将内容更新到数据库.译者添加去转义字符命令stripslashes
						update_option( $value['id'], stripslashes($_REQUEST[ $value['id'] ]  )); } 
					else { 
						delete_option( $value['id'] ); 
						} 
						}
				//更新标题栏
                header("Location: themes.php?page=functions.php&saved=true");
                die;

        } else if( 'reset' == $_REQUEST['action'] ) { //reset按下的动作

            foreach ($options as $value) {
                delete_option( $value['id'] ); }
			//更新标题栏
            header("Location: themes.php?page=functions.php&reset=true");
            die;

        }
    }
	//调用WP函数add_theme_page.回调函数是mytheme_admin(),显示的名字就是主题名+"Options"Options这几个字可以换成别的.
    add_theme_page($themename." Options", "".$themename." Options", 'edit_themes', basename(__FILE__), 'mytheme_admin');

}

function mytheme_admin() {

    global $themename, $shortname, $options;
	//保存后的提示信息,settings saved.可以替换成中文
    if ( $_REQUEST['saved'] ) echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings saved.</strong></p></div>';
	//重置后的提示信息,settings reset可以替换成中文
    if ( $_REQUEST['reset'] ) echo '<div id="message" class="updated fade"><p><strong>'.$themename.' settings reset.</strong></p></div>';
    
?>
<div class="wrap">
<!--整个Options页面的标题.完全可以随意发挥.-->
<h2><?php echo $themename; ?> settings</h2>

<form method="post">



<?php foreach ($options as $value) { 
    
	switch ( $value['type'] ) {
	
		case "open":
		?>
		<!--open里table开始了.-->
        <table width="100%" border="0" style="background-color:#eef5fb; padding:10px;">
		
        
        
		<?php break;
		
		case "close":
		?>
		
        </table><br />
        
        
		<?php break;
		
		case "title":
		?>
		<table width="100%" border="0" style="background-color:#dceefc; padding:5px 10px;"><tr>
        	<td colspan="2"><h3 style="font-family:Georgia,'Times New Roman',Times,serif;"><?php echo $value['name']; ?></h3></td>
        </tr>
                
        
		<?php break;

		case 'text':
		?>
        
        <tr>
            <td width="20%" rowspan="2" valign="middle"><strong><?php echo $value['name']; ?></strong></td>
            <td width="80%"><input style="width:400px;" name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>" type="<?php echo $value['type']; ?>" value="<?php if ( get_settings( $value['id'] ) != "") { echo stripslashes( get_settings( $value['id'] )); } else { echo $value['std']; } ?>" /></td>
        </tr>

        <tr>
            <td><small><?php echo $value['desc']; ?></small></td>
        </tr><tr><td colspan="2" style="margin-bottom:5px;border-bottom:1px dotted #000000;">&nbsp;</td></tr><tr><td colspan="2">&nbsp;</td></tr>

		<?php 
		break;
		
		case 'textarea':
		?>
        <!--我一直觉得作者用的textarea有点大,可以调小一点儿.-->
        <tr>
            <td width="20%" rowspan="2" valign="middle"><strong><?php echo $value['name']; ?></strong></td>
            <td width="80%"><textarea name="<?php echo $value['id']; ?>" style="width:400px; height:200px;" type="<?php echo $value['type']; ?>" cols="" rows=""><?php if ( get_settings( $value['id'] ) != "") { echo get_settings( $value['id'] ); } else { echo $value['std']; } ?></textarea></td>
            
        </tr>

        <tr>
            <td><small><?php echo $value['desc']; ?></small></td>
        </tr><tr><td colspan="2" style="margin-bottom:5px;border-bottom:1px dotted #000000;">&nbsp;</td></tr><tr><td colspan="2">&nbsp;</td></tr>

		<?php 
		break;
		
		case 'select':
		?>
		<!--这里还藏了一个select类型可以用.应该是上传用的吧?-->
        <tr>
            <td width="20%" rowspan="2" valign="middle"><strong><?php echo $value['name']; ?></strong></td>
            <td width="80%"><select style="width:240px;" name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>"><?php foreach ($value['options'] as $option) { ?><option<?php if ( get_settings( $value['id'] ) == $option) { echo ' selected="selected"'; } elseif ($option == $value['std']) { echo ' selected="selected"'; } ?>><?php echo $option; ?></option><?php } ?></select></td>
       </tr>
                
       <tr>
            <td><small><?php echo $value['desc']; ?></small></td>
       </tr><tr><td colspan="2" style="margin-bottom:5px;border-bottom:1px dotted #000000;">&nbsp;</td></tr><tr><td colspan="2">&nbsp;</td></tr>

		<?php
        break;
            
		case "checkbox":
		?>
            <tr>
            <td width="20%" rowspan="2" valign="middle"><strong><?php echo $value['name']; ?></strong></td>
                <td width="80%"><? if(get_settings($value['id'])){ $checked = "checked="checked""; }else{ $checked = ""; } ?>
                        <input type="checkbox" name="<?php echo $value['id']; ?>" id="<?php echo $value['id']; ?>" value="true" <?php echo $checked; ?> />
                        </td>
            </tr>
                        
            <tr>
                <td><small><?php echo $value['desc']; ?></small></td>
           </tr><tr><td colspan="2" style="margin-bottom:5px;border-bottom:1px dotted #000000;">&nbsp;</td></tr><tr><td colspan="2">&nbsp;</td></tr>
            
        <?php 		break;
	
 
} 
}
?>

<!--</table>-->
<!--俩按钮.-->
<p class="submit">
<input name="save" type="submit" value="Save changes" />    
<input type="hidden" name="action" value="save" />
</p>
</form>
<form method="post">
<p class="submit">
<input name="reset" type="submit" value="Reset" />
<input type="hidden" name="action" value="reset" />
</p>
</form>

<?php
}
//在进入控制面板的时候计入选项页
add_action('admin_menu', 'mytheme_add_admin'); ?>

后台页面就OK了。在后台选中默认主题激活就可以看到选项页了。

****使用选项****
现在我们要做的是让添加的选项能用起来。这次,打开header.php
我们的任务有:

1.从数据库读取选项
2.判断禁用的checkbox功能是不是选上了,如果没有,才进行下一步
3.判断标题是否存在,如果存在就显示
4.否则,显示基本的“Welcom”
5.判断欢迎语是否存在,存在就显示
6.不存在就显示点儿别的
7.checkbox如果选上了,就什么都不显示。

1.读数据库选项

在 header.php 的底部,添加

<?php
global $options;
foreach ($options as $value) {
    if (get_settings( $value['id'] ) === FALSE) { $$value['id'] = $value['std']; } else { $$value['id'] = get_settings( $value['id'] ); }
}
?>

上面的代码提取了我们所添加的选项,它们是:

$wpc_welcome_disable

$wpc_welcome_title

$wpc_welcome_message

2. 查看“禁用”选项

<?php
if ($wpc_welcome_disable == "false") { ?>

checkbox选中的时候,$wpc_welcome_disable值就是true,未选中就是false。接下来的动作只有未选中的时候才进行。

3. 查看是否有title并显示

<?php

if ($wpc_welcome_title) { ?>
<h4><?php echo $wpc_welcome_title; ?></h4>

用个H4显示欢迎语的标题

4.否则,显示默认标题

<?php } else { ?>
<h4>Welcome!</h4>
<?php } ?>

如果标题没设就显示Welcom

5 & 6. 查看并显示欢迎语的内容

<?php if ($wpc_welcome_message) { ?>
<p><? echo $wpc_welcome_message; ?></p>
<?php } else { ?>
<p>Hello and welcome to our site. We hope you enjoy your stay!</p>
<?php } ?>

跟上一步差不多但是这次用到的是$wpc_welcome_message 。

7. 如果没选中,就什么都不显示

<?php } else { ?>

    <!-- You could insert something here which will display when the box IS checked. -->

<?php } ?>

虽然不重要,但这几句不能省,不如编不过。

最后。如果你按照上面的步骤一步一步做下来,应该就能学会添加自己的option页了。

已有21条评论

  1. 青年一代都接受了要先记得感谢国家了。。

  2. 呵呵,无折腾不WP,我也去搞搞

  3. 唉,看了很久也没看懂,想用也不知道怎么整了,还是景仰一下博主,呵呵~~

  4. 复杂了点儿,我现在的WP还是默认主题,飘过。。。。

  5. 有点复杂,不过看了两边就懂了。HOHO

    感谢博主分享啊。

  6. 很高质量的一篇文章!写了几个插件和几个模板,没见来流量啊

  7. 干嘛非得加选项?直接源代码中加JS不可以吗?

  8. 看了前半部分,觉得有需要,收藏之,以后细看。

  9. 这一片的目的就是为了说明怎么加选项页.
    选项页的意义在于方便维护.
    至于欢迎语就是个例子,怎么加不都是加.

  10. WP很强大,善于动手的人更强大

  11. 貌似政治上有一句话:人和动物的区别就在于使用工具

  12. 我这里的沙发有得是,不值钱的.

  13. 嗯,想了想,还是觉得很有用,星号。可以加个选项页换header的图片什么的~~~嗯,不行我要忍住,以后再说。
    这个很适合那种发布模板的人呢~~~

  14. 这个很有用的。。比如philna那个主题 好多功能我都不知道怎么扒下来。。都在主题选项里
    不过你的教程要是能写的更多更详细就好啦~方便我等小白

  15. 能自己折腾主题的就不算小白了.
    其实就模板和调用两部分,没多少代码的.

  16. 确实比较复杂。。。比我用的还麻烦,先收藏

  17. 太好啦,最近在做主题,刚好可以用得到。呃,感谢国家培养了博主,给我们带来了这篇好文…

  18. 对于我这种抓吗们考代码的,肯定是不懂的!

  19. 确实啊 这方面的资料太少了 坐下来慢慢研究代码

  20. 折腾折腾生活更美好。我是代码盲,一点也不懂。但我知道,每一点的小成就都会让我兴奋不已。。

    1. 难得你在旧贴上留言.其实这篇东西已经有点儿过时了,从WP加了预览功能之后这种方法就有些老土了.
      虽然我是程序员,但PHP完全是业余爱好,折腾折腾有益健康,预防帕金森.

你好,新朋友。留言前请先填写昵称邮箱