小工具

小工具(Widget)将内容和功能添加到小工具区域(也称为侧边栏)。小工具区域为用户提供了一种定制网站的方式。一个小工具区域可以出现在多个页面上,也可以只出现在一个页面上。主题可能只有一个小工具区域,也可能有很多。

你可以使用小工具区域的一些例子:

  • 使用小工具布置主页,这使网站所有者能够决定在其主页的每个部分应该出现什么。
  • 创建一个用户可以用自己的内容定制的页脚。
  • 在博客上添加一个可定制的侧边栏。

小工具是一个可以输出一些HTML的PHP对象,同一种小工具可以在同一个页面上多次使用(例如文本小工具)。小工具可以在数据库中保存数据(在选项表中)。

当你创建了一种新的小工具,它将出现在用户的管理界面上,在外观>小工具。用户可以在WordPress管理中把小工具添加到小工具区域并定制小工具的设置。

内置与独立的小工具

在默认的WordPress安装中包含了一组小工具。除了这些标准的小工具外,额外的小工具可以由主题或插件包含。内置在主题或插件中的小工具的一个优点是提供额外的功能和增加小工具的数量。

一个缺点是,如果一个主题被改变或一个插件被停用,该插件或主题小工具的功能将丢失。然而,小工具的数据和偏好设置将被保存到选项表中,如果主题或插件被重新激活,则会恢复。

如果你在主题中包含一个小工具,它只能在该主题处于启用状态时使用。如果用户决定改变他们的主题,将失去对该小工具的访问。然而,如果小工具是与插件一起包含的,用户可以改变他们的主题而不失去对小工具功能的访问。

 

剖析小工具

在视觉上,一个小工具包括两个区域:

  1. 标题区域
  2. 小工具选项

例如,这是管理界面和前端的内置文本小工具的布局:

Sample Editable Widget
在管理区域的小工具
A widget as it appars to a site visitor.
访客看到的小工具样子

这个小工具输出的HTML看起来像:

<div id="text-7" class="widget widget_text">
<!-- Widget Container -->
    <div class="widget-wrap">
        <h4 class="widgettitle">This is a text widget</h4>
        <!-- Title -->
        <div class="textwidget">
        <!-- Content of Widget -->
            I can put HTML in here. <a href="http://google.com/">Search me!</a>
        </div>
    </div>
</div>

每个小工具都有自己的方式来输出与所显示数据相关的HTML,小工具的包装标签是由显示它的小工具区域定义的。

创建一个像内置文本小工具一样的小工具所需的PHP代码看起来像这样:

<?php

class My_Widget extends WP_Widget {

    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. 确保主题至少有一个小工具区,可以添加小工具。

 

你的widget类

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
    }
}

?>

这些函数的文档可以在widget类代码中找到:

  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类的widget类。

在类的构造函数中,你将调用父类的构造函数,并将widget的基本ID和名字传给它。同时,你将使用widgets_init动作钩子来注册小工具。

接下来,你将声明在创建小工具时要使用的参数。必须定义四个参数,before_title, after_title, before_widget, and after_widget。这些参数将定义包裹小工具标题和小工具本身的代码。

在定义完参数后,你将定义widgets函数,这个函数需要两个参数,即$args和$instance,这个函数将处理来自表单的选项,并在你网站的前端显示widget的HTML。在上面的例子中,widget函数只是输出widget的标题,同时通过widget_title过滤器。然后,它输出一个简单的小工具包装器和小工具文本字段的内容。正如例子中所概述的,你可以从存储在$instance中的widget访问这些选项。

接下来你将定义表单函数。这个函数接受一个参数,$instance,并输出用户用来在Widgets管理界面上创建widget的表单。在上面的例子中,该函数首先定义$title和$text变量,并将它们设置为先前输入的值,如果这些值存在的话。然后,它输出一个简单的表单,其中有一个文本字段的标题和一个文本内容的文本区。

然后,你将定义更新函数。这个函数需要两个参数,$new_instance和$old_instance,并负责在提交时用新的选项更新你的小工具。这里你只需将$instance定义为一个空数组。然后将标题和文本键设置为$new_instance的值,如果它们存在的话。然后你返回$instance。

最后,当以上所有的定义完成后,你将新的widget类实例化并测试你的工作。

 

小工具样板

<?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 {
    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' );
}
?>

 

特别注意事项

如果你想在另一个模板文件中使用小工具,而不是在侧边栏中,你可以使用the_widget()来以编程方式显示它。该函数接受widget的类名。你可以像这样向函数传递小工具类的名称:

<?php the_title(); ?>

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

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

如果你需要在一个页面的特定区域使用小工具,你可能想使用这种方法,例如在你网站首页的某个部分的表格旁边显示一个事件列表,或者在导航旁边的大菜单上显示一个电子邮件表格。