如何使 WordPress 插件可扩展
已发表: 2022-03-10您是否曾经使用过插件并希望它做一些不同的事情? 也许您需要一些超出插件设置页面范围的独特东西。
我个人遇到过这种情况,我打赌你也遇到过。 如果您是 WordPress 插件开发人员,很可能您的一些用户在使用您的插件时也遇到过这种情况。
这是一个典型的场景:你终于找到了能满足你所有需求的插件——除了一件小事。 没有启用那个小东西的设置或选项,所以您浏览文档并发现您无能为力。 您在 WordPress 插件的支持论坛中请求该功能 - 但没有骰子。 最后,您将其卸载并继续搜索。
想象一下,如果你是这个插件的开发者。 如果用户要求某些特定功能,您会怎么做?
理想的做法是实施它。 但是,如果该功能用于非常特殊的用例,那么添加它是不切实际的。 拥有一个只有 0.1% 的用户会使用的插件设置并不好。
您只想实现影响大多数用户的功能。 实际上,80% 的用户使用 20% 的功能(80/20 规则)。 因此,在实施之前,请确保任何新功能都受到强烈要求,并且 80% 的用户会从中受益。 如果您为请求的每个功能都创建了一个设置,那么您的插件就会变得复杂和臃肿——没有人想要这样。
最好的办法是使插件可扩展,代码明智,以便其他人可以根据自己的需要增强或修改它。
在本文中,您将了解为什么让您的插件可扩展是一个好主意。 我还将分享一些关于我如何学会做到这一点的技巧。
是什么让插件可扩展?
简而言之,可扩展插件意味着它遵循面向对象编程的 SOLID 原则的“O”部分——即开放/封闭原则。
如果您不熟悉开放/封闭原则,这基本上意味着其他人不应该为了修改某些内容而编辑您的代码。
将此原则应用于 WordPress 插件,这意味着如果插件中包含允许其他人修改其行为的规定,则该插件是可扩展的。 就像 WordPress 允许人们“挂钩”到 WordPress 的不同区域一样,但在插件级别。
插件的典型示例
让我们看看如何创建一个可扩展的插件,从一个不能扩展的示例插件开始。
假设我们有一个插件,它生成一个侧边栏小部件,显示三个最新帖子的标题。 该插件的核心是一个简单地将这三个帖子的标题包装在列表标签中的函数:
function get_some_post_titles() { $args = array( 'posts_per_page' => 3, ); $posts = get_posts( $args ); $output = '
- ';
foreach ( $posts 作为 $post ) {
$输出 .= '
- ' . $post->post_title 。 ' '; } $输出 .= '
虽然这段代码可以工作并完成工作,但它的可扩展性并不好。
为什么? 因为函数是以自己的方式设置的,所以如果不直接修改代码,就无法改变它的行为。
如果用户想要显示三个以上的帖子,或者可能包含带有帖子标题的链接怎么办? 上面的代码没有办法做到这一点。 用户被插件的工作方式所困扰,无法改变它。
包括一百个设置不是答案
有多种方法可以增强上述插件以允许用户对其进行自定义。
一种这样的方法是在设置中添加很多选项,但即使这样也可能无法满足用户希望从插件中获得的所有可能性。
如果用户想要执行以下任何操作(我们稍后会重新讨论的场景)怎么办:
- 显示特定类别的 WooCommerce 产品或帖子;
- 在另一个插件提供的轮播中显示项目,而不是简单的列表;
- 执行自定义数据库查询,然后在列表中使用这些查询的帖子。
如果我们向我们的小部件添加一百个设置,那么我们将能够涵盖上述用例。 但是,如果其中一种情况发生了变化,现在用户只想显示当前有货的 WooCommerce 产品怎么办? 小部件需要更多设置来适应这一点。 很快,我们就会有大量的设置。
此外,具有大量设置列表的插件并不完全是用户友好的。 如果可能,请避开这条路线。
那么,我们将如何解决这个问题呢? 我们会让插件可扩展。
添加我们自己的钩子以使其可扩展
通过研究上面的插件代码,我们看到 main 函数执行的一些操作:
- 它使用
get_posts
获取帖子。 - 它生成一个帖子标题列表。
- 它返回生成的列表。
如果其他人要修改这个插件的行为,他们的工作很可能会涉及这三个操作。 为了使我们的插件可扩展,我们必须在这些周围添加钩子,以便为其他开发人员打开它们。
一般来说,这些是为插件添加钩子的好地方:
- 在主要流程周围和内部,
- 在构建输出 HTML 时,
- 用于更改帖子或数据库查询,
- 在从函数返回值之前。
可扩展插件的典型示例
根据这些经验法则,我们可以添加以下过滤器以使我们的插件可扩展:
- 添加
myplugin_get_posts_args
用于修改get_posts
的参数, - 添加
myplugin_get_posts
以覆盖get_posts
的结果, - 添加
myplugin_list_item
用于自定义列表条目的生成, - 添加
myplugin_get_some_post_titles
以覆盖返回的生成列表。
这是添加了所有钩子的代码:
function get_some_post_titles() { $args = array( 'posts_per_page' => 3, ); // Let other people modify the arguments. $posts = get_posts( apply_filters( 'myplugin_get_posts_args', $args ) ); // Let other people modify the post array, which will be used for display. $posts = apply_filters( 'myplugin_get_posts', $posts, $args ); $output = '
- ';
foreach ( $posts 作为 $post ) {
// 让其他人修改列表条目。
$输出 .= '
- ' . apply_filters('myplugin_list_item', $post->post_title, $post) 。 ' '; } $输出 .= '
您还可以在 GitHub 存档中获取上述代码。

我在这里添加了很多钩子,这可能看起来不切实际,因为示例代码非常简单和小,但它说明了我的观点:通过仅添加四个钩子,其他开发人员现在可以以各种方式自定义插件的行为。
Hooks 的命名空间和上下文
在继续之前,请注意关于我们已实现的钩子的两个重要事项:
- 我们使用
myplugin_
为钩子命名空间。
这确保了钩子的名称不会与其他插件的钩子冲突。 这只是一个好习惯,因为如果调用另一个具有相同名称的钩子,它可能会导致不需要的效果。 - 我们还在上下文的所有钩子中传递了对
$args
的引用。
我这样做是为了如果其他人使用此过滤器来更改代码流中的某些内容,他们可以使用该$args
参数作为参考来了解调用挂钩的原因,以便他们可以相应地执行调整。
我们的钩子的效果
还记得我之前谈到的独特场景吗? 让我们重新审视这些,看看我们的钩子如何使它们成为可能:
- 如果用户想要显示来自特定类别的 WooCommerce 产品或帖子,那么他们可以使用过滤器
myplugin_get_posts_args
在插件查询帖子时添加自己的参数,或者他们可以使用myplugin_get_posts
用自己的列表完全覆盖帖子。 - 如果用户想在另一个插件提供的轮播中显示项目,而不是作为一个简单的列表,那么他们可以使用
myplugin_get_some_post_titles
覆盖该函数的整个输出,而是从那里输出一个轮播。 - 如果用户想要执行自定义数据库查询,然后在列表中使用该查询的帖子,那么与第一个场景类似,他们可以使用
myplugin_get_posts
来使用自己的数据库查询并更改帖子数组。
好多了!
如何使用我们的过滤器的快速示例
开发人员可以使用add_filter
挂钩到我们上面的过滤器(或使用add_action
进行操作)。
以我们上面的第一个场景为例,开发人员可以使用我们创建的myplugin_get_posts_args
过滤器执行以下操作来显示 WooCommerce 产品:
add_filter( 'myplugin_get_posts_args', 'show_only_woocommerce_products' ); function show_only_woocommerce_products( $args ) { $args['post_type'] = 'product'; return $args; }
我们也可以使用动作挂钩
除了使用apply_filters
之外,我们还可以使用do_action
使我们的代码可扩展。 两者的区别在于前者允许其他人更改变量,而后者允许其他人在我们代码的各个部分执行附加功能。
使用动作时,我们实质上是向其他开发人员公开插件的流程,并让他们一起执行其他操作。
它在我们的示例中可能没有用(因为我们只显示一个短代码),但它在其他示例中会有所帮助。 例如,给定一个可扩展的备份插件,我们可以创建一个插件,该插件还将备份文件上传到第三方服务,如 Dropbox。
“伟大的! 但我为什么要关心让我的插件可扩展呢?”
好吧,如果你仍然不相信这个想法,这里有一些关于为什么允许其他人修改你的插件行为是一个好主意的想法。
它为插件打开了更多自定义的可能性
每个人都有不同的需求。 而且你的插件很有可能不能满足所有这些,你也不能预料到它们。 打开插件以允许修改插件行为的关键区域可以创造奇迹。
它允许人们在不接触插件代码的情况下进行修改
其他开发人员不会被迫直接更改您的插件文件。 这是一个巨大的好处,因为直接修改插件的文件通常是不好的做法。 如果插件得到更新,那么您的所有修改都将被清除。
如果我们添加自己的钩子供其他人使用,那么插件的修改可以放在外部位置 - 比如说,在另一个插件中。 这样一来,原插件完全不会被触动,并且可以在不破坏任何东西的情况下自由更新,并且其他插件中的所有修改都将保持不变。
结论
可扩展插件真的很棒,为我们提供了很多定制可能性的空间。 如果您使您的插件可扩展,您的用户和其他开发人员会因此而爱上您。
看看 WooCommerce、Easy Digital Downloads 和 ACF 等插件。 这些插件是可扩展的,你可以很容易地分辨出来,因为 WordPress 插件目录中的许多其他插件都向它们添加了功能。 它们还提供了广泛的动作和过滤器钩子来修改插件的各个方面。 我在上面列举的经验法则已经出现在我对它们的研究中。
以下是使您的插件可扩展的一些要点:
- 遵循开闭原则。 其他人不应该为了修改某些内容而编辑您的代码。
要使您的插件可扩展,请在以下位置添加挂钩:
- 在主要流程周围和内部,
- 在构建输出 HTML 时,
- 用于更改帖子或数据库查询,
- 在从函数返回值之前。
- 使用插件名称命名您的钩子名称,以防止命名冲突。
- 尝试传递与钩子相关的其他变量,以便其他人了解钩子中发生的情况。
- 不要忘记记录插件的钩子,以便其他人可以了解它们。
延伸阅读
如果您想了解更多关于扩展插件的信息,这里有一些资源:
- 如何使您的 WordPress 插件可扩展,GitHub
本文中的所有示例代码。 - “开始使用 WordPress Hooks 的有用技巧”,Thomas Maier,Smashing Magazine
- “如何创建 WordPress 插件”,Smashing Magazine 的 Daniel Pataki
- “Hooks”,插件手册,WordPress.org