hook 系统方法
Hooks are a fundamental concept for WordPress developers. In previous articles on SitePoint, we’ve learned what hooks are and their importance, the two types of hooks: actions
and filters
with code examples of how they work, and an alternative way of firing actions and filters events and how to hook static and non-static class methods to actions and filters.
钩子是WordPress开发人员的基本概念。 在SitePoint的先前文章中,我们了解了钩子的含义及其重要性,钩子的两种类型: actions
和filters
,以及有关其工作方式的代码示例,以及触发动作和过滤器事件的另一种方法,以及如何钩住静态和用于操作和过滤器的非静态类方法 。
In this article, I will cover how to hook methods of an instantiated class (object) to actions and filters, how to integrate a namespaced class method to a hook, caveats of using namespaces in WordPress hook system and solution to them.
在本文中,我将介绍如何将实例化类(对象)的方法挂钩到动作和过滤器,如何将命名空间的类方法集成到挂钩,在WordPress挂钩系统中使用命名空间的注意事项及其解决方案。
挂钩对象方法 (Hooking Object Methods)
Assume you were tasked by your employer to build an ad manger plugin for a large news website, to make ad insertion to news content seamless. This is how you might go about building it.
假设您受雇主委托为大型新闻网站构建广告管理器插件,以使广告内容无缝插入新闻内容。 这就是您构建它的方式。
You would create an AdManager
class with a number of methods that contain the various ad-networks ad-code.
您将使用许多包含各种广告网络广告代码的方法来创建AdManager
类。
class AdManager {
/**
* AdSense unit code.
*/
public function adsense() { ?>
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<ins class="adsbygoogle"
style="display:inline-block;width:336px;height:280px"
data-ad-client="ca-pub-xxxxxxxxxxxxxxxx"
data-ad-slot="6762452247"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<?php }
/**
* Buysellads ad code.
*/
public function buysellads() {
// ...
}
}
Say a website theme has an action
called before_post_content
that is fired before the post content is displayed and you want to hook the adsense
method to it to display the ad before any post content. How would you go about it?
假设某个网站主题有一个名为before_post_content
的action
,该action
在显示帖子内容之前触发,并且您希望将adsense
方法挂接到该主题上,以在任何帖子内容之前显示广告。 你会怎么做?
You are trying to hook the method to an action outside of the class unlike the examples we’ve seen in part 2 where it was done in the class constructor like so:
您试图将方法挂接到类外部的操作上,这与我们在第2部分中看到的示例不同,该示例是在类构造函数中完成的,如下所示:
public function __construct() {
add_action( 'before_post_content', array( $this, 'adsense' ) );
}
To hook the adsense
method to the before_post_content
action outside of the class (probably in the functions.php
file of the active website theme) in order to display the Google AdSense ads before every post’s content, you will have to replace $this
with an instance of the class.
要将adsense
方法与类外部的before_post_content
操作挂钩(可能在活动网站主题的functions.php
文件中),以便在每个帖子的内容之前显示Google AdSense广告,则必须用实例替换$this
班上的
add_action( 'before_post_content', array( new AdManager(), 'adsense' ) );
And say the class includes a method that returns a singleton instance of the class.
并说该类包括一个返回该类的单例实例的方法。
class AdManager {
// ...
/**
* Singleton class instance.
*
* @return AdManager
*/
public static function get_instance() {
static $instance = null;
if ( $instance == null ) {
$instance = new self();
}
return $instance;
}
}
Here is how the adsense
method can be hooked to the before_post_content
action.
这是adsense
方法可以如何链接到before_post_content
操作的方法。
add_action( 'before_post_content', array( AdManager::get_instance(), 'adsense' ) );
命名空间 (Namespaces)
The WordPress hook system was developed at a time when there was no namespace feature in WordPress. As a result, you might find it difficult to hook a namespaced function and class method to an action
and filter
.
WordPress挂钩系统是在WordPress中没有名称空间功能时开发的。 结果,您可能会发现很难将命名空间的函数和类方法挂接到action
和filter
。
Say your AdManager
class has a namespace of SitePoint\Plugin
as follows.
假设您的AdManager
类具有以下SitePoint\Plugin
命名空间。
namespace SitePoint\Plugin;
class AdManager {
// ...
}
To hook the adsense
method of the AdManager
class to the before_post_content
action, you must prepend the class name with the namespace like so:
要将AdManager
类的adsense
方法挂接到before_post_content
操作中,您必须在类名称前添加名称空间,如下所示:
add_action( 'before_post_content', array( SitePoint\Plugin\AdManager::get_instance(), 'adsense' ) );
If the class
and the add_action
function call is in the same PHP file namespaced by SitePoint\Plugin\
, prepending the namespace to the class name is unnecessary because they are covered by the same global namespace.
如果class
和add_action
函数调用位于由SitePoint\Plugin\
命名的同一个PHP文件中,则不需要将命名空间放在类名之前,因为它们被同一全局命名空间覆盖。
Enough of class examples, let’s now see a plain function.
足够的类示例,让我们现在看一个简单的函数。
Say you have the following namespaced function to be hooked to the wp_head
action.
假设您将以下命名空间函数挂接到wp_head
操作。
namespace SitePoint\Plugin;
function google_site_verification() {
echo '<meta name="google-site-verification" content="ytl89rlFsAzH7dWLs_U2mdlivbrr_jgV4Gq7wClHDUJ8" />';
}
Here’s how it can be done with the namespace prepended to the function:
这是在函数前添加名称空间的方法:
add_action( 'wp_head', 'SitePoint\Plugin\google_site_verification' );
Hook系统给我的命名空间带来了恐怖 (My Namespace Horror with the Hook System)
In my Admin Bar & Dashboard Access Control plugin, I registered an uninstall hook that deletes the plugin option when it’s uninstalled.
在我的Admin Bar&Dashboard访问控制插件中,我注册了一个卸载钩子 ,该钩子在卸载时会删除该插件选项。
Something as easy as the following lines of code shouldn’t be a problem where PP_Admin_Bar_Control
is the class name and on_uninstall
is the method called when uninstalled.
只需使用以下几行代码就可以解决问题,其中PP_Admin_Bar_Control
是类名, on_uninstall
是卸载时调用的方法。
register_uninstall_hook( __FILE__, array( 'PP_Admin_Bar_Control', 'on_uninstall' ) );
To be sure it works, I tried uninstalling the plugin to see if the plugin option will be deleted but to my surprise, I got the following error.
为了确保它能正常工作,我尝试卸载插件以查看插件选项是否将被删除,但令我惊讶的是,出现以下错误。
The plugin generated 2137 characters of unexpected output during activation.
Mind you, here is how the class and register_uninstall_hook
function are defined with a namespace of ProfilePress\PP_Admin_Bar_Control
.
请注意,这是如何使用ProfilePress\PP_Admin_Bar_Control
的命名空间定义类和register_uninstall_hook
函数的。
namespace ProfilePress\PP_Admin_Bar_Control;
register_uninstall_hook( __FILE__, array( 'PP_Admin_Bar_Control', 'on_uninstall' ) );
class PP_Admin_Bar_Control {
// ...
/** Callback to run when the uninstalled hook is called. */
public static function on_uninstall() {
if ( ! current_user_can( 'activate_plugins' ) ) {
return;
}
delete_option( 'abdc_options' );
}
// ...
}
Can you spot the reason why the on_uninstall
class method wasn’t triggered when the plugin is uninstalled?
您能on_uninstall
卸载插件时未触发on_uninstall
类方法的原因吗?
You would think since the register_uninstall_hook
function is defined under the namespace, the class should be covered by it, but that is not the case. You still need to prepend the namespace to the class as follows for it to work.
您可能会认为,因为register_uninstall_hook
函数是在名称空间下定义的,所以该类应该包含在该名称空间中,但事实并非如此。 您仍然需要按如下所示将名称空间添加到该类之前,以便它起作用。
register_uninstall_hook( __FILE__, array( 'ProfilePress\PP_Admin_Bar_Control\PP_Admin_Bar_Control', 'on_uninstall' ) );
I actually had a hard time figuring out the problem. I decided I don’t want to let you go through the same stress and head-banging that I went through.
实际上,我很难解决这个问题。 我决定我不想让你经历我经历过的同样的压力和撞击。
结论 (Conclusion)
Quirks like this make some developers cringe and stay away from WordPress. We shouldn’t forget WordPress was developed at the time when PHP lacked all the language improvement and features it has now. I always try to figure out how to circumvent these quirks and then teach it to people.
这样的怪癖使一些开发人员畏缩并远离WordPress。 我们不能忘记WordPress是在PHP缺乏所有语言改进和功能时开发的。 我总是试图弄清楚如何规避这些怪癖,然后将其教给人们。
I hope I have been able to demystify the hook system in WordPress. If you have any questions or contributions, please let us know in the comments.
我希望我能够揭开WordPress中的钩子系统的神秘面纱。 如果您有任何疑问或贡献,请在评论中告知我们。
翻译自: https://www.sitepoint.com/understanding-namespaces-wordpress-hook-system/
hook 系统方法