WordPress开发教程(五)之开发插件

这篇文章记录了如何编写自己的插件,这样的话,你就可以修改WordPress网站,第三方插件,甚至是主题的功能。

Hook(钩子),Action和Filter

制作插件之前,让我们看下Hook,action和filter,它们是整个插件系统的基础,能够帮助你完全理解WordPress的工作原理。

我们想要创建一个插件,可以向网站上添加一些数据分析跟踪代码。跟踪代码一般都是放在网页的底部(</body>标签的前面)。

之前提到过,必须要将wp_head()wp_footer()函数添加到主题中。wp_footer()函数可以执行由插件定义的其它函数。

1
2
3
4
5
function my_tracking_code() {
echo 'Paste tracking code from Google Analytics here';
}
add_action( 'wp_footer', 'my_tracking_code' );

上面代码中,我们编写了输出跟踪代码的函数,它只是放在插件中的一个函数。接着,使用add_action()函数,告诉WordPress什么时候该执行我们的函数。

当WordPress执行到wp_footer()函数时,它会发现所有的被它钩住(使用add_action())的函数。然后会一步一步地执行这些函数。

术语

Hook是WordPress插件API的一部分,而action和filter是两种不同类型的hook。action允许你添加功能,你通常定义一个函数,WordPress处理hook的时候,就会运行该函数;而filter是用来修改存在的功能,例如,WordPress有个hook,可以决定文章摘要的长度,你可以使用filter来修改摘要的长度。

add_action()函数接收四个参数:hook的名字(函函数在哪执行),被钩住的函数的名字(需要执行哪个函数),优先级(函数被执行的顺序),函数接收的参数(被钩住的函数接收参数的数量)。

WordPress不仅仅会在主题中提供action,也会在后台管理页面和用户特定的动作上下文中。publish_post这个hook在文章被发表时会执行;此时接收的参数变得非常重要,如果向这个hook上添加一个函数,应该需要知道哪篇文章发表以及文章的详情;通过文档,该函数需要传递文章ID和文章数据。

下面的代码实现:当发表文章时,需要发送电子邮件给文章作者:

1
2
3
4
5
6
7
8
9
10
11
12
13
function our_author_notification( $id, $post ) {
$author = $post->post_author;
$name = get_the_author_meta( 'display_name', $author );
$email = get_the_author_meta( 'user_email', $author );
$link = get_permalink( $id );
$message = 'Hello ' . $name . ", \n\n" . "Your artcile <a href='" . $link . "'>" . $post->post_title . "</a> has been published.";
wp_mail( $email, 'One of your posts has been published', $message );
}
add_action( 'publish_post', 'our_author_notification', 10, 2 );

filter会修改数据,所以在被钩住的函数中会返回一些数据。使用add_filter()函数进行添加filter。

我们可以使用filter来修改文章摘要最后面的更多显示格式,默认是[...]

1
2
3
4
5
function our_excerpt_more( $more ) {
return 'there's more...';
}
add_filter( 'excerpt_more', 'our_excerpt_more' );

注意:上面没有声明优先级和接收的参数数量;默认值:优先级为10,接收的参数数量为1;在被钩住的函数中,并没有使用传递过来的参数,仅仅是返回一个字符串。

可以使用相同的方法在文章内容的第一段落中嵌入广告:

1
2
3
4
5
6
function in_content_ad( $content ) {
$ad = '<div class="in-content-ad"><img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=Advertisement&w=250&h=250"></div>';
return $ad . $content;
}
add_filter( 'the_content', 'in_content_ad' );

了解hook是如何定义的以及如何创建我们自己的hook有助于理解系统的工作原理。假如我们创建一个电子商务的插件,添加列出商品的功能:

1
2
3
$products = get_products( 10 );
show_products();

上面明显是硬编码的,如果别人只想显示三个商品呢?可以使用hook来解决这个问题。

1
2
3
4
$product_count = apply_filters( 'product_count', 10 );
$products = get_products( $product_count );
show_products();

apply_filter()函数告诉WordPress,有个叫作product_count的hook,我们想要运行被它钩住的所有函数。

1
2
3
4
5
add_filter( 'product_count', 'carousel_product_count' );
function carousel_product_count( $count ) {
return 3;
}

插件创建的基础

插件位于WordPress网站的主插件目录中,通常是wp-content/plugins。下面,我们创建一个插件,在文章下面添加一个tweet链接。

首先在插件目录下创建一个目录,命名为tweet-plugin,在该目录下创建一个文件,命名为tweet-plugin.php,将下面的代码粘贴到里面:

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
Plugin Name: Tweet Plugin
Plugin URI: http://www.somethingaboutchina.com
Description: Used to be a social link
Version: 1.0.0
Author: wflytoc
Author URI: https://antmoving.github.io
License: GPL2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: tweet-plugin
Domain Path: /languages
*/

上面的信息会展示在网站的后台管理界面的插件部分,保存该文件后,你会看到列出的新插件;虽然它现在没有做什么事情,但可以激活它。

我们现在要做的就是找到方式来将tweet链接添加到文章内容后面;换种方式思考,其实就是通过在文章内容后面添加一些文本来修改文章内容。我们需要使用the_content钩子:

1
2
3
4
5
6
function tweet_link($content) {
return $content . '<p><a href="https://www.baidu.com">Go to Baidu</a></p>';
}
add_filter('the_content','tweet_link');

所有的插件都是函数和钩子的结合,用于决定这些函数在哪里执行。

向插件中添加主题选项

有许多方式来向主题中添加选项,下面来看一种默认的方式;首先在后台管理中创建一个页面,用来存放表单:

1
2
3
4
5
6
7
8
9
10
add_action('admin_menu', 'tweetlink_settings_menu');
function tweetlink_settings_menu() {
add_menu_page('Tweet Link Settings', 'Tweet Link', 'manage_options', 'tweetlink-settings', 'tweetlink_settings_page', 'dashicons-twitter');
}
function tweetlink_settings_page() {
echo '<div class="wrap"><h2>Tweet Link Options</h2></div>';
}

tweetlink_settings_menu()函数被钩在admin_menu上,这是菜单项创建的方式。大量的工作都是通过add_menu_page函数来完成的,该函数接收许多参数来创建一个顶级的页面,参数列表如下:

  • 页面标题:用在<title>标签中
  • 菜单题目:用在左侧的菜单上
  • 权限能力:能够看到该菜单选项的最小权限能力
  • 菜单slug:用在URL中的slug
  • 函数:控制页面内容输出的函数
  • 图标:图片URL
  • 位置:菜单中的子项位置

总是要考虑将选项页面放在一个已经存在的菜单中,上面的页面最好放在Setting部分,通过使用add_otions_pages()函数。

下一步是让WordPress知道我们的tweet设置,在被admin_init钩子钩住的函数中使用register_settings()来进行注册选项变量。代码如下:

1
2
3
4
5
6
add_action( 'admin_init', 'tweetlink_settings' );
function tweetlink_settings() {
register_setting( 'tweetlink_settings', 'twitter_account' );
}

register_setting()函数接收两个参数:选项变量所在的组名和选项变量名。

下一步是添加一个表单来使用我们的选项变量,使用下面的代码作为模板来创建我们自己的设置。使用settings_fields()do_settings_sections()函数来让WordPress来保存数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function tweetlink_settings_page() {
?>
<div class="wrap">
<h2>Tweet Link Settings</h2>
<form method="post" action="options.php">
<?php settings_fields( 'tweetlink_settings' ); ?>
<?php do_settings_sections( 'tweetlink_settings' ); ?>
<table class="form-table">
<tr valign="top">
<th scope="row">Twitter Account</th>
<td><input type="text" name="twitter_account" value="<?php echo esc_attr( get_option('twitter_account') ); ?>" /></td>
</tr>
</table>
<?php submit_button(); ?>
</form>
</div>
<?php
}

此时,你可以看到新的设置字段,可以填写和保存。然后在插件的任何地方都可以使用get_option('twitter_account')来获取对应的值。