WordPress 基础开发 – 一探 WordPress Hook 机制及示例应用

WordPress 教程 6个月前 (03-17) 0

 本文行文思路及示例代码来自 WPMUDEV 同名文章,感谢原作者。禁止转载。

 Hook 机制是 事件驱动型架构 中相当举足轻重的一部分。总的来说,Hook 机制实际上为我们深度定制「 WordPress 」提供了一条捷径。

 简言之,「事件驱动型架构」是一种「通过监听事件状态并作出反应」的设计。发布文章、编辑主题、安装插件……任何一个动作实质上都对应着一个「事件」的发生。而 Hook 就如同刚刚所描述的那样——在代码和实际操作中修出一条捷径,令我们可以根据自己所想而不断丰富和拓展 WordPress。

 来举个简单的例子,「发布文章」就是一个再常见不过的示例——publish_post 除此之外当然还有对应的delete_post  等等(可在 WordPress Codex 上详阅各种 Hook 的具体作用)。可别小看 WordPress 所定义的这几个小「短语」,它们就是 WordPress 可被拓展的重要基础。毫不夸张地说,正是 Hook 让 WordPress 拥有了这么完备的生态圈(Ecosystem),以及数以万计的插件及主题。

 再来说说为什么我们非用 Hook 不可?

 还记得我们是怎么更新 WordPress 的吗?通常只需要点击仪表盘上的「立即更新」按钮,喝杯茶的功夫一切就搞定了。开发者们甚至不需要过多考虑为新版 WordPress 做出适配和调整——很多时候,连一行代码都不需要修改。这就是 Hook 的魅力所在,正因如此,WordPress 团队才能够通过仅更新一份代码,就让世界上近 10% 的网站不用担心程序本身所带来的安全风险。

钩子(Hooks),动作(Actions),过滤器(Filters)?这尼玛都是啥? 

 究其本质,钩子(Hooks)是 WordPress 各种主题/插件 中的一些公有事件。

 可我们为什么要叫它……「钩子」呢?

 来看看这些场景:在发布文章的同时通知百度来爬下网站,或是在保存草稿后自动帮我获取第一张图片作为特色图像等等……开发者们总想着让自己的代码能够伴随着某个操作一起执行,正如一个「钩子」一样。 

 钩子总共分为两种类型:

  • 动作 Actions
  • 过滤器 Filters

 我们在之后会介绍它们之间的区别。

Action Hooks 和 Filter Hooks 之间的区别

 Actions 和 Filters 基本上可以互换着用——它们都是通过一定的「参数」来获取数据的,只是实现的逻辑和写法略有不同(如果你详细读过 WordPress 的核心代码,即会发现 Action Hooks 实际上就是由 Filter Hooks 实现的 )。

 不过它们还有一项非常关键的区别:Filter Hooks 必须返回一个实际值(value),Action Hooks 则不需要。

在实际场景中,Filter Hooks 通常更专注于「内容」方面。例如说,Filter Hook title_save_pre 是作用于文章标题的, content_save_pre 就是作用于文章内容的。另一方面,Action Hooks 顾名思义,它偏向于「在 WordPress 做某件事时执行相应的动作」,还是拿 publish_post 为例,这个 Action Hook 就是在「任意一篇文章被发表时」被触发。

我该怎么用 Action Hook 呢?

 基本语句如下:

 其中的$hook 就是你所指定的钩子,$function_to_add 就是在「钩子满足条件被触发时」所执行的相关函数。后面的$priority, $accepted_args 先不管,我们以后再说。

 稍安勿躁,等会我会介绍怎么把 Action Hook 用于具体的场景中。

我该怎么用 Filter Hook 呢?

 Filter Hook 就是在「我只想获取/修改某个内容」时所使用。

 基本语句如下:

 和之前的add_action 超像对吧?同样地,$hook 就是你所指定的钩子,$function_to_add 就是在「钩子满足条件被触发时」所执行的相关函数。

怎么删除钩子?

 诶等等,我干嘛要没事干删除掉好不容易定义的钩子?可别忘了 WordPress 许多核心功能就是由一个一个钩子所建立联系的。删除钩子好比带走了队伍中的某几个人,即使他们不在了——也不会影响到整个队伍的连续性。

应用实例

注:所有 Filter Hooks 及 Action Hooks 都可以在 WordPress Codex 中被找到。Hookr.io 上收录了不少 Hooks 的使用示例,有时比官方还全哦。

 在写完这篇文章时,WordPress 已有超过 1900 个可被使用的钩子……只有你搜不到,没有它做不到。

 

Filter Hook 示例 #1

使用场景:给每篇文章后面加一条链接。

实现过程:

 从 WordPress Codex 中了解到, content_save_pre 可以实现「动态更改内容」的目的(Allow you to sanitize content prior to saving it in the database)。

代码示例:

 大功告成啦!

 等等!那add_filter 后面多出的10,1 是什么?这就是之前我们没介绍到的$priority 和 $accepted_args 。

$priority – 优先级

 设想:如果有很多个地方都添加同一个 Hook ,他们会怎么决定执行的先后顺序呢?这时$priority  即起到作用。所设定的数值越小,则越靠前被执行;反之则越延后。这也就是为什么许多代码片段会给$priority  设定出莫名其妙的 9999 ——实际上就是令其最后一个被执行。

$accepted_args – 传参

 这个应该很好理解,就是所被 Hook 的函数中所需要传递的参数。例如本例子的参数就是$content ,在 add_filter  被设置为 1。

 

Filter Hook 示例 #2

使用场景:实现 SEO 插件中的「更改网站标题」功能

实现过程:

 例如我的网站:「WP酷 – 最前沿的 WordPress 资源聚合平台」,如果我想更改其中的分隔符「 – 」呢?

 通过查阅文档得知,title_save_pre 可以实现「动态更改标题」的目的。大同小异,仿照 「示例 #1」即可写出相应代码。不过需要注意的是:Filter Hook 必须返回一个有效的值哦!

代码示例: 

Action Hook 示例 #1

使用场景:在发布文章后自动发布微博、说说……

使用过程:

 还是 publish_post ……猜都可以知道这个钩子是在 WordPress 后台点击「发布」按钮时所执行的(An action triggered whenever a post is published, or if it is edited and the status is changed to publish.)。

 就这么简单。

 

Action Hook 示例 #2

使用场景:在用户完成注册后发送一条欢迎邮件

使用过程:

 after_signup_user 是「在用户注册之后」所触发的动作,不再赘述。

代码示例:

 注意到了吗?add_action 所指定的函数并没有像之前那样需要返回一个固定值。 

还有什么是 WordPress Hooks 可以做的?

 如果你细心观察,许多的主题中都会出现 <?php wp_head(); ?> 或是 <?php wp_footer(); ?> 此类的身影。在看完本文后或许就能明白:这两个函数是为主题的可定制性所准备的——开发者们可以通过 Functions.php 直接将函数 Hook 到wp_head 等之类的位置上。包括各类 SEO 插件、编辑器插件等等等等,它们都是通过 Hooks 达到「不修改主题本身」却实现了许多新功能的效果。