真香,30天做一套wordpress主题(第6天):侧边栏
我们将尽量保持文章的循序渐进和通俗易懂,请确保自己已经掌握了那一篇文章的全部内容时才选择跳过,不然可能会错过关键的信息噢~
这里我们假定你已经知晓了以下基础知识,这些基础知识对理解文章内容是至关重要的:
1. HTML/CSS/JS基础
2. PHP基础
3. 如何使用Wordpress
4. 如何搭建web环境
如果你已经知晓了以上基础知识,恭喜你,本系列的任何文章内容对你而言都没有什么难度。
伟大的侧边栏
今天我们开始制作主题的侧边栏(sidebar),wordpress可以把小工具(widgets)放到侧边栏里,我们先为主题开启侧边栏功能,在functions.php里添加如下代码:
function my_sidebar_registration() {
register_sidebar(array(
'name' => __( 'Sidebar'),
'id' => 'sidebar-1',
));
}
add_action( 'widgets_init', 'my_sidebar_registration' );
我们就可以后台看到官方默认的一些widgets了,当然,我们还会需要自定义widgets,但是现在,我们先对这些默认widgets提供支持:

看上去有点多,不过没关系,只要把小工具的通用容器设计好了,很多内容都是重复的。我们首先配上一个Categories小工具,然后在首页侧边栏的位置显示出来。
<aside class="sidebar">
<?php dynamic_sidebar('my-sidebar'); ?>
</aside>
这里对于官方的小工具,我们不去动它的DOM结构,只通过CSS进行样式描述就可以了:

还记得我们的my_sidebar_registration吗?我们在里面把一些官方的小工具在我们的主题里去掉,比如image audio video这些,会破坏AMP的规则,其它的暂时没用到的我们也屏蔽了:
unregister_widget('WP_Widget_Media_Audio'); // remove audio
unregister_widget('WP_Widget_Media_Video'); // remove video
unregister_widget('WP_Widget_Media_Image'); // remove image
unregister_widget('WP_Widget_Media_Gallery'); // remove galley
unregister_widget('WP_Widget_Calendar'); // remove calendar
unregister_widget('WP_Nav_Menu_Widget'); // remove nav menu
unregister_widget('WP_Widget_Pages'); // remove pages menu
unregister_widget('WP_Widget_RSS'); // remove rss
unregister_widget('WP_Widget_Text'); // remove text
unregister_widget('WP_Widget_Tag_Cloud'); // remove tag cloud
鉴于我们需要amp-form保证页面的amp属性,只能把搜索小工具也给移除了,然后我们来手写一个自定义搜索小工具,这里我们为了偷懒直接从wordpress源文件里复制一个WP_Widget_Search修改使用。
第一步,引入amp-form文件(header.php):
<script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>
第二步,建立自定义搜索小工具类(functions.php):
class my_search extends WP_Widget {
public function __construct() {
$widget_ops = array(
'classname' => 'widget_search',
'description' => __( 'A search form for your site.' ),
'customize_selective_refresh' => true,
);
parent::__construct( 'search', _x( 'Search', 'Search widget' ), $widget_ops );
}
public function widget( $args, $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : '';
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
echo $args['before_widget'];
if ( $title ) {
echo $args['before_title'] . $title . $args['after_title'];
}
echo
'<form target="_top" role="search" method="get" class="search-form" action="/">
<input type="text" class="search-field" placeholder="' . esc_attr_x( 'Search …', 'placeholder' ) . '" value="' . get_search_query() . '" name="s" />
<button type="submit" class="search-submit"></button>
</form>';
echo $args['after_widget'];
}
public function form( $instance ) {
$instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
$title = $instance['title'];
?>
<p><label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?> <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" /></label></p>
<?php
}
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$new_instance = wp_parse_args( (array) $new_instance, array( 'title' => '' ) );
$instance['title'] = sanitize_text_field( $new_instance['title'] );
return $instance;
}
}
这里我们需要知道,__construct构造函数对这个小工具的基本信息进行了描述,form方法定义了后台添加小工具时看到的选项,update方法定义了更新小工具设置时数据的更新,widget方法定义了小工具在前台的展现结构。
第三步,注册这个小工具:
register_widget('my_search');
最后我们就可以在后台使用我们自定义的搜索小工具了,添加后到页面上看看:

这里有一个要特别注意的地方,amp-form对action里的url是有要求的,虽然可以是完整的url也可以是绝对路径,但是最终使用的action url必须是https协议的,否则无法通过amp checker的检测。
总结和预告
今天我们完成了侧边栏的开发,并且创建了属于我们的自定义小工具,通过定义通用css样式,大多数的小工具都直接美化好了,对于不能用的官方小工具,我们先直接屏蔽了
明天我们将稍加休整一下,完成页面的通用底部,实现顶部菜单的二级展开,做一些细节上的优化。
如果你喜欢这个系列的文章,赶快关注我们(数字江湖异志录)吧,不要错过后续的更多干货噢。
wordpress后台制作教程-设置选项类文件
上一篇教程中我们介绍了一个配置wordpress后台选项的类文件构架,这里就将由wp自学笔记整理的类文件源码贴出示众。
版本控制
2013.07.08,版本1.0
- 增加数组类型
- 修改复选框功能
- 添加编辑器功能
懒人下载
- <?php
-
-
-
-
-
- class ashu_option_class{
-
- var $options;
- var $pageinfo;
- var $database_options;
- var $saved_optionname;
-
-
- function ashu_option_class($options, $pageinfo) {
- $this->options = $options;
- $this->pageinfo = $pageinfo;
- $this->make_data_available();
-
- add_action( \'admin_menu\', array(&$this, \'add_admin_menu\') );
-
- if( isset($_GET[\'page\']) && ($_GET[\'page\'] == $this->pageinfo[\'filename\']) ) {
-
- add_action(\'admin_init\', array(&$this, \'enqueue_head\'));
- }
- }
-
- function enqueue_head() {
-
- wp_enqueue_script(\'ashu_options_js\', TEMJS_URI.\'ashu_options.js\');
- wp_enqueue_style(\'ashu_options_css\', TEMJS_URI.\'ashu_options.css\');
- wp_enqueue_script(\'thickbox\');
- wp_enqueue_style(\'thickbox\');
- }
-
-
- function add_admin_menu() {
-
- $top_level = \"主题设置\";
- if(!$this->pageinfo[\'child\']) {
- add_menu_page($top_level, $top_level, \'edit_themes\', $this->pageinfo[\'filename\'], array(&$this, \'initialize\'));
- define(\'TOP_LEVEL_BASEAME\', $this->pageinfo[\'filename\']);
- }else{
- add_submenu_page(TOP_LEVEL_BASEAME, $this->pageinfo[\'full_name\'], $this->pageinfo[\'full_name\'], \'edit_themes\', $this->pageinfo[\'filename\'], array(&$this, \'initialize\'));
- }
- }
-
- function make_data_available() {
- global $ashu_option;
-
- foreach ($this->options as $option) {
- if( isset($option[\'std\']) ) {
- $ashu_option_std[$this->pageinfo[\'optionname\']][$option[\'id\']] = $option[\'std\'];
- }
- }
-
- $this->saved_optionname = \'ashu_\'.$this->pageinfo[\'optionname\'];
- $ashu_option[$this->pageinfo[\'optionname\']] = get_option($this->saved_optionname);
-
-
- $ashu_option[$this->pageinfo[\'optionname\']] = array_merge((array)$ashu_option_std[$this->pageinfo[\'optionname\']], (array)$ashu_option[$this->pageinfo[\'optionname\']]);
-
-
- $ashu_option[$this->pageinfo[\'optionname\']] = $this->htmlspecialchars_deep($ashu_option[$this->pageinfo[\'optionname\']]);
-
- }
-
-
- function htmlspecialchars_deep($mixed, $quote_style = ENT_QUOTES, $charset = \'UTF-8\') {
- if (is_array($mixed) || is_object($mixed)) {
- foreach($mixed as $key => $value) {
- $mixed[$key] = $this->htmlspecialchars_deep($value, $quote_style, $charset);
- }
- }
- elseif (is_string($mixed)) {
- $mixed = htmlspecialchars_decode($mixed, $quote_style);
- }
- return $mixed;
- }
-
- function initialize() {
- $this->get_save_options();
- $this->display();
- }
-
-
- function display() {
- $saveoption = false;
- echo \'<div class=\"wrap\">\';
- echo \'<div class=\"icon32\" id=\"icon-options-general\"><br/></div>\';
- echo \'<h2>\'.$this->pageinfo[\'full_name\'].\'</h2>\';
- echo \'<form method=\"post\" action=\"\">\';
-
-
- foreach ($this->options as $option) {
- if (method_exists($this, $option[\'type\'])) {
- $this->$option[\'type\']($option);
- $saveoption = true;
- }
- }
- if($saveoption) {
- echo \'<p class=\"submit\">\';
- echo \'<input type=\"hidden\" value=\"1\" name=\"save_my_options\"/>\';
- echo \'<input type=\"submit\" name=\"Submit\" class=\"button-primary autowidth\" value=\"Save Changes\" /></p>\';
- }
- echo \'</form></div>\';
- }
-
-
- function get_save_options() {
- $options = $newoptions = get_option($this->saved_optionname);
- if ( isset( $_POST[\'save_my_options\'] ) ) {
- echo \'<div class=\"updated fade\" id=\"message\" style=\"\"><p><strong>Settings saved.</strong></p></div>\';
- $opion_count = 0;
- foreach ($_POST as $key => $value) {
- if( preg_match(\"/^(numbers_)/\", $key, $result) ){
- $numbers = explode( \',\', $value );
- $newoptions[$key] = $numbers;
- }elseif( preg_match(\"/^(tinymce_)/\", $key, $result) ){
- $value = stripslashes($value);
- $newoptions[$key] = $value;
- }elseif( preg_match(\"/^(checkbox_)/\", $key, $result) ){
- $newoptions[$key] = $value;
- }else{
- $value = stripslashes($value);
- $newoptions[$key] = htmlspecialchars($value, ENT_QUOTES,\"UTF-8\");
- }
- }
- }
-
- if ( $options != $newoptions ) {
- $options = $newoptions;
- update_option($this->saved_optionname, $options);
- }
-
- if($options) {
- foreach ($options as $key => $value) {
- $options[$key] = empty($options[$key]) ? false : $options[$key];
- }
- }
-
- $this->database_options = $options;
- }
-
-
- function open($values) {
- if(!isset($values[\'desc\'])) $values[\'desc\'] = \"\";
-
- echo \'<table class=\"widefat\">\';
- echo \'<thead><tr><th colspan=\"2\">\'.$values[\'desc\'].\' </th></tr></thead>\';
- }
-
-
- function close($values) {
- echo \'<tfoot><tr><th> </th><th> </th></tr></tfoot></table>\';
- }
-
-
- function title($values) {
- echo \'<h3>\'.$values[\'name\'].\'</h3>\';
- if (isset($values[\'desc\'])) echo \'<p>\'.$values[\'desc\'].\'</p>\';
- }
-
-
- function textarea($values) {
- if(isset($this->database_options[$values[\'id\']]))
- $values[\'std\'] = $this->database_options[$values[\'id\']];
-
- echo \'<tr valign=\"top\" >\';
- echo \'<th scope=\"row\" width=\"200px\">\'.$values[\'name\'].\'</th>\';
- echo \'<td>\'.$values[\'desc\'].\'<br/>\';
- echo \'<textarea name=\"\'.$values[\'id\'].\'\" cols=\"60\" rows=\"7\" id=\"\'.$values[\'id\'].\'\" style=\"width: 80%; font-size: 12px;\" class=\"code\">\';
- echo $values[\'std\'].\'</textarea><br/>\';
- echo \'<br/></td>\';
- echo \'</tr>\';
- }
-
-
- function text($values) {
- if(isset($this->database_options[$values[\'id\']])) $values[\'std\'] = $this->database_options[$values[\'id\']];
-
- echo \'<tr valign=\"top\" >\';
- echo \'<th scope=\"row\" width=\"200px\">\'.$values[\'name\'].\'</th>\';
- echo \'<td>\'.$values[\'desc\'].\'<br/>\';
- echo \'<input type=\"text\" size=\"\'.$values[\'size\'].\'\" value=\"\'.$values[\'std\'].\'\" id=\"\'.$values[\'id\'].\'\" name=\"\'.$values[\'id\'].\'\"/>\';
- echo \'<br/><br/></td>\';
- echo \'</tr>\';
- }
-
-
-
- function checkbox($values) {
- if(isset($this->database_options[$values[\'id\']])) $values[\'std\'] = $this->database_options[$values[\'id\']];
-
- echo \'<tr valign=\"top\">\';
- echo \'<th scope=\"row\" width=\"200px\">\'.$values[\'name\'].\'</th>\';
- echo \'<td>\'.$values[\'desc\'].\'<br/>\';
-
- foreach( $values[\'buttons\'] as $key=>$value ) {
- $checked =\"\";
- if( is_array($values[\'std\']) && in_array($key,$values[\'std\'])) {
- $checked = \'checked = \"checked\"\';
- }
- echo \'<input \'.$checked.\' type=\"checkbox\" class=\"kcheck\" value=\"\'.$key.\'\" name=\"\'.$values[\'id\'].\'[]\"/>\'.$value;
- }
-
-
- echo \'<label for=\"\'.$values[\'id\'].\'\">\'.$values[\'desc\'].\'</label><br/>\';
- echo \'<br/></td>\';
- echo \'</tr>\';
- }
-
-
- function radio($values) {
- if(isset($this->database_options[$values[\'id\']])) $values[\'std\'] = $this->database_options[$values[\'id\']];
-
- echo \'<tr valign=\"top\" >\';
- echo \'<th scope=\"row\" width=\"200px\">\'.$values[\'name\'].\'</th>\';
- echo \'<td>\'.$values[\'desc\'].\'<br/>\';
-
- foreach($values[\'buttons\'] as $key=>$value) {
- $checked =\"\";
- if(isset($values[\'std\']) && ($values[\'std\'] == $key)) {
- $checked = \'checked = \"checked\"\';
- }
-
- echo \'<p><input \'.$checked.\' type=\"radio\" class=\"kcheck\" value=\"\'.$key.\'\" name=\"\'.$values[\'id\'].\'\"/>\';
- echo \'<label for=\"\'.$values[\'id\'].\'\">\'.$value.\'</label></p>\';
- }
-
- echo \'<br/></td>\';
- echo \'</tr>\';
- }
-
- function numbers_array($values){
- if(isset($this->database_options[$values[\'id\']]))
- $values[\'std\'] = $this->database_options[$values[\'id\']];
- else
- $values[\'std\']=array();
-
- $nums = implode( \',\', $values[\'std\'] );
-
- echo \'<tr valign=\"top\" >\';
- echo \'<th scope=\"row\" width=\"200px\">\'.$values[\'name\'].\'</th>\';
- echo \'<td>\'.$values[\'desc\'].\'<br/>\';
- echo \'<input type=\"text\" size=\"\'.$values[\'size\'].\'\" value=\"\'.$nums.\'\" id=\"\'.$values[\'id\'].\'\" name=\"\'.$values[\'id\'].\'\"/>\';
- echo \'<br/><br/></td>\';
- echo \'</tr>\';
- }
-
-
- function dropdown($values) {
- if(!isset($this->database_options[$values[\'id\']]) && isset($values[\'std\'])) $this->database_options[$values[\'id\']] = $values[\'std\'];
-
- echo \'<tr valign=\"top\" >\';
- echo \'<th scope=\"row\" width=\"200px\">\'.$values[\'name\'].\'</th>\';
- echo \'<td>\'.$values[\'desc\'].\'<br/>\';
-
- if($values[\'subtype\'] == \'page\') {
- $select = \'Select page\';
- $entries = get_pages(\'title_li=&orderby=name\');
- }else if($values[\'subtype\'] == \'sidebar\'){
- global $wp_registered_sidebars;
- $select = \'Select a special sidebar\';
- $entries = $wp_registered_sidebars;
- }else if($values[\'subtype\'] == \'cat\'){
- $select = \'Select category\';
- $entries = get_categories(\'title_li=&orderby=name&hide_empty=0\');
- }
- else
- {
- $select = \'Select...\';
- $entries = $values[\'subtype\'];
- }
-
- echo \'<select class=\"postform\" id=\"\'. $values[\'id\'] .\'\" name=\"\'. $values[\'id\'] .\'\"> \';
- echo \'<option value=\"\">\'.$select .\'</option> \';
-
- foreach ($entries as $key => $entry) {
- if($values[\'subtype\'] == \'page\')
- {
- $id = $entry->ID;
- $title = $entry->post_title;
- }else if($values[\'subtype\'] == \'cat\'){
- $id = $entry->term_id;
- $title = $entry->name;
- }else if($values[\'subtype\'] == \'sidebar\'){
- $id = $entry[\'id\'];
- $title = $entry[\'name\'];
- }
- else
- {
- $id = $key;
- $title = $entry;
- }
-
- if ($this->database_options[$values[\'id\']] == $id )
- {
- $selected = \"selected=\'selected\'\";
- }
- else
- {
- $selected = \"\";
- }
-
- echo\"<option $selected value=\'\". $id.\"\'>\". $title.\"</option>\";
- }
-
- echo \'</select>\';
-
- echo \'<br/><br/></td>\';
- echo \'</tr>\';
- }
-
-
- function upload($values) {
- $prevImg = \'\';
- if(isset($this->database_options[$values[\'id\']])) $values[\'std\'] = $this->database_options[$values[\'id\']];
- if($values[\'std\'] != \'\'){$prevImg = \'<img src=\'.$values[\'std\'].\' alt=\"\" />\';}
-
- echo \'<tr valign=\"top\" >\';
- echo \'<th scope=\"row\" width=\"200px\">\'.$values[\'name\'].\'</th>\';
- echo \'<td>\';
- echo \'<div class=\"preview_pic_optionspage\" id=\"\'.$values[\'id\'].\'_div\">\'.$prevImg.\'</div>\';
- echo $values[\'desc\'].\'<br/>\';
- echo \'<input type=\"text\" size=\"60\" value=\"\'.$values[\'std\'].\'\" name=\"\'.$values[\'id\'].\'\" class=\"upload_pic_input\" />\';
- echo \' <a onclick=\"return false;\" title=\"\" class=\"k_hijack button thickbox\" id=\"\'.$values[\'id\'].\'\" href=\"media-upload.php?type=image&hijack_target=\'.$values[\'id\'].\'&TB_iframe=true\">Insert Image</a>\';
-
- echo \'<br/><br/></td>\';
- echo \'</tr>\';
- }
-
- function tinymce($values){
- if(isset($this->database_options[$values[\'id\']]))
- $values[\'std\'] = $this->database_options[$values[\'id\']];
-
- echo \'<tr valign=\"top\" >\';
- echo \'<th scope=\"row\" width=\"200px\">\'.$values[\'name\'].\'</th>\';
- echo \'<td>\'.$values[\'desc\'].\'<br/>\';
- wp_editor( $values[\'std\'], $values[\'id\'],$settings=array(\'tinymce\'=>1,\'media_buttons\'=>0,) );
- echo \'<br/></td>\';
- echo \'</tr>\';
- }
-
- }
- ?>