小部件(Widget)会在一个侧边栏区域(也称为 侧边栏)中添加内容和功能。侧边栏区域为用户自定义网站提供了一种方式。侧边栏区域可以出现在多个页面或仅出现于单个页面上。您的主题可能只有一个侧边栏区域,也可能有很多个。

以下是您可以使用侧边栏区域的一些示例:

  • 使用小部件布局主页。这允许网站所有者决定其主页每个部分应显示什么内容。
  • 创建一个用户可以自定义内容的页脚(Footer)。
  • 为博客添加一个可自定义的侧边栏。

小部件是一个输出一些 HTML 的 PHP 对象。同一种类的小部件可以在同一页面多次使用(例如文本小部件)。小部件可以将数据保存到数据库(在 options 表中)。

当您创建新类型的小部件时,它将在用户的 外观 > 小部件管理屏幕中显示出来。用户可以将该小部件添加到侧边栏区域,并从 WordPress 后台自定义小部件设置。

内置与独立小部件

默认 WordPress 安装中包含一套小部件。除了这些标准小部件外,主题或插件还可以包含额外的小部件。嵌入在主题或插件中的小部件的一个优势是提供额外的功能并增加小部件的数量。

一个缺点是,如果更改了主题或禁用了插件,该插件或小部件的功能将会丢失。但是,来自小部件的数据和偏好设置将保存到 options 表中,并在重新启用主题或插件时恢复。

如果您在主题中包含一个小部件,则只有在该主题处于活动状态时才能使用该小部件。如果用户决定更改其主题,他们将无法访问该小部件。但是,如果小部件是随插件一起包含的,用户可以更换主题而不会失去对该小部件功能的访问权限。

小部件的结构

从视觉上看,一个小部件由两个区域组成:

  1. 标题区域(Title Area)
  2. 小部件选项(Widget Options)

例如,这是内置文本小部件在后台和前台的布局:

示例可编辑的小部件
后台区域中的小部件表单。
网站访客看到的小部件
网站访客看到的小部件。

此小部件的 HTML 输出如下所示:

<div id="text-7" class="widget widget_text">

	<div class="widget-wrap">

		<h4 class="widgettitle">
			This is a text widget
		</h4><!-- .widgettitle -->

		<div class="textwidget">
			I can put HTML in here. <a href="http://google.com/">Search me!</a>
		</div><!-- .textwidget -->

	</div><!-- .widget-wrap -->

</div><!-- #text-7 -->

每个小部件都有输出与其显示的数据相关的 HTML 的特定方式。小部件的包装标签由正在显示它的侧边栏区域定义。

创建类似内置文本小部件的小部件所需的 PHP 代码如下所示:

<?php
class My_Widget extends WP_Widget {
	public function __construct() {
		parent::__construct(
			'my-text',  // Base ID
			'My Text'   // Name
		);
		add_action( 'widgets_init', function() {
			register_widget( 'My_Widget' );
		});
	}

	public $args = array(
		'before_title'  => '<h4 class="widgettitle">',
		'after_title'   => '</h4>',
		'before_widget' => '<div class="widget-wrap">',
		'after_widget'  => '</div></div>',
	);

	public function widget( $args, $instance ) {
		echo $args['before_widget'];
		if ( ! empty( $instance['title'] ) ) {
			echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
		}
		echo '<div class="textwidget">';
		echo esc_html__( $instance['text'], 'text_domain' );
		echo '</div>';
		echo $args['after_widget'];
	}

	public function form( $instance ) {
		$title = ! empty( $instance['title'] ) ? $instance['title'] : esc_html__( '', 'text_domain' );
		$text  = ! empty( $instance['text'] ) ? $instance['text'] : esc_html__( '', 'text_domain' );
		?>
		<p>
			<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php echo esc_html__( 'Title:', 'text_domain' ); ?></label>
			<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
		</p>
		<p>
			<label for="<?php echo esc_attr( $this->get_field_id( 'Text' ) ); ?>"><?php echo esc_html__( 'Text:', 'text_domain' ); ?></label>
			<textarea class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'text' ) ); ?>" type="text" cols="30" rows="10"><?php echo esc_attr( $text ); ?></textarea>
		</p>
		<?php
	}

	public function update( $new_instance, $old_instance ) {
		$instance          = array();
		$instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
		$instance['text']  = ( ! empty( $new_instance['text'] ) ) ? $new_instance['text'] : '';
		return $instance;
	}
}
$my_widget = new My_Widget();

上述代码将在文章稍后部分详细解释。

开发小部件

要创建和显示一个小部件,您需要执行以下操作:

  1. 通过扩展标准 WP_Widget 类及其部分功能来创建您的小部件类。
  2. 注册您的小部件,以便在小部件屏幕中可用。
  3. 确保您的主题至少有一个可以添加小部件的 侧边栏区域。

您的小部件类

WP_Widget 类位于 wp-includes/class-wp-widget.php

<?php
class My_Widget extends WP_Widget {
	public function __construct() {
		// actual widget processes
	}

	public function widget( $args, $instance ) {
		// outputs the content of the widget
	}

	public function form( $instance ) {
		// outputs the options form in the admin
	}

	public function update( $new_instance, $old_instance ) {
		// processes widget options to be saved
	}
}

这些功能的文档可以在小部件类代码中找到:

  1. construct:在后台使用描述、名称和显示宽度设置您的小部件。
  2. widget:处理小部件选项并在页面上显示 HTML。$args 参数提供可用于显示小部件标题类和小部件内容类的 HTML。
  3. form:显示用于设置您的小部件选项的表单。如果您的小部件没有任何选项,您可以跳过此函数(尽管即使为空也最好包含它)。
  4. update:将小部件选项保存到数据库。如果您的小部件没有任何选项,您可以跳过此函数(尽管即使为空也最好包含它)。

注册一个小部件

register_widget() 函数用于注册小部件。

使用 widgets_init 钩子调用此函数:

<?php
add_action( 'widgets_init', 'wpdocs_register_widgets' );
function wpdocs_register_widgets() {
	register_widget( 'My_Widget' );
}

包装小部件的 HTML,以及标题和小部件内容的类,是在使用 register_sidebar() 注册侧边栏区域时指定的。

示例

文本小部件示例

要构建本文开头示例中的文本小部件。您将从设置一个扩展 WP_Widget 类的小部件类开始。

在类的构造函数中,您将调用父级构造函数并传递您的小部件的基本 ID 和名称。同样在类的构造函数中,您将挂钩到 widgets_init 动作以注册您的小部件。

接下来,您将在创建小部件时声明要使用的参数。必须定义四个参数:before_title、after_title、before_widget和 after_widget。这些参数将定义包装您的小部件标题和小部件本身的代码。

在定义了参数之后,您将定义小部件函数。该函数接受两个参数:前面的 <$args 数组和小部件的<$instance,它是处理来自表单的选项并在网站前台显示 HTML 以用于小部件的函数。在上例中,小部件函数仅输出小部件标题,同时将其通过 widget_title过滤器传递。然后它输出一个简单的小部件包装器和小部件文本字段的内容。正如示例中所概述的那样,您可以访问存储在<$instance 中的来自小部件的选项。

接下来您将定义表单函数。该函数接受一个参数 <$instance,并输出用户用于在后台小部件屏幕中创建小部件的表单。在上例中,该函数首先定义 $title 和$text 变量并将它们设置为之前输入的值的值(如果这些值存在)。然后它输出了一个简单的表单,其中包含标题的文本字段和文本内容的文本区域。

最后您将定义 update 函数。该函数接受两个参数 <$new_instance 和<$old_instance,并在提交时负责使用新选项更新您的小部件。在这里您只需将 $instance 定义为空数组。然后如果存在则将 title 和 text 键设置为 $new_instance 的值。然后返回$Instance。

最后,当上述所有内容都定义后,您将实例化您的新小部件类并测试您的工作。

示例小部件

<?php
/**
 * Adds Foo_Widget widget.
 */
class Foo_Widget extends WP_Widget {
	/**
	 * Register widget with WordPress.
	 */
	public function __construct() {
		parent::__construct(
			'foo_widget', // Base ID
			'Foo_Widget', // Name
			array( 'description' => __( 'A Foo Widget', 'text_domain' ) ) // Args
		);
	}
	/**
	 * Front-end display of widget.
	 *
	 * @see WP_Widget::widget()
	 *
	 * @param array $args     Widget arguments.
	 * @param array $instance Saved values from database.
	 */
	public function widget( $args, $instance ) {
		extract( $args );
		$title = apply_filters( 'widget_title', $instance['title'] );
		echo $before_widget;
		if ( ! empty( $title ) ) {
			echo $before_title . $title . $after_title;
		}
		echo __( 'Hello, World!', 'text_domain' );
		echo $after_widget;
	}
	/**
	 * Back-end widget form.
	 *
	 * @see WP_Widget::form()
	 *
	 * @param array $instance Previously saved values from database.
	 */
	public function form( $instance ) {
		if ( isset( $instance['title'] ) ) {
			$title = $instance['title'];
		} else {
			$title = __( 'New title', 'text_domain' );
		}
		?>
		<p>
			<label for="<?php echo $this->get_field_name( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
			<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 ); ?>" />
		 </p>
		<?php
	}
	/**
	 * Sanitize widget form values as they are saved.
	 *
	 * @see WP_Widget::update()
	 *
	 * @param array $new_instance Values just sent to be saved.
	 * @param array $old_instance Previously saved values from database.
	 *
	 * @return array Updated safe values to be saved.
	 */
	public function update( $new_instance, $old_instance ) {
		$instance          = array();
		$instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
		return $instance;
	}
} // class Foo_Widget

此示例小部件可以在 widgets_init 钩子中注册:

<?php
// Register Foo_Widget widget
add_action( 'widgets_init', 'register_foo' );
function register_foo() {
	register_widget( 'Foo_Widget' );
}

使用命名空间的示例

如果您在使用 PHP 5.3 和命名空间,您应该像以下示例一样直接调用构造函数:

<?php
namespace a\b\c;

class My_Widget_Class extends \WP_Widget {
	public function __construct() {
		parent::__construct( 'baseID', 'name' );
	}
	// ... rest of the functions
}

并使用以下代码注册小部件:

<?php
// Register Foo_Widget widget
add_action( 'widgets_init', 'register_my_widget' );
function register_my_widget() {
	register_widget( 'a\b\c\My_Widget_Class' );
}

有关更多详细信息,请参见 Stack Exchange 上的此答案。

特殊考虑事项

如果您想在模板文件中(而不是侧边栏中)使用小部件,您可以使用 the_widget() 程序化地显示它。该函数接受小部件类名称。您像这样将小部件类名传递给函数:

<?php the_title(); ?>

<div class="content">
	<?php the_content(); ?>
</div><!-- .content -->

<div class="widget-section">
	<?php the_widget( 'My_Widget_Class' ); ?>
</div><!-- .widget-section -->

如果您需要在页面的特定区域使用小部件,例如在您的网站主页部分的表单旁边显示事件列表或在巨型菜单上显示电子邮件捕获表单与导航并列,您可能希望使用这种方法。