php - wordpress 如何制作动作/过滤器挂钩?(在其功能中附加您的功能)
问题描述
我对 Wordpress 使用什么概念来创建他们拥有的很棒的功能感兴趣:动作和过滤器。
有谁知道他们是如何工作的,以及如何在任何非 wordpress 应用程序/项目中创建类似的功能?
PS 只是想再澄清一下,以防万一,我知道如何在 wordpress 中使用它们,我对它们的实际工作方式很感兴趣。
谢谢!
解决方案
像这样的东西:
class mediator{
protected $actions = [];
protected static $instance;
private function __construct(){}
private function __clone(){}
public static function getInstance(){
if(!self::$instance) self::$instance = new self;
return self::$instance;
}
public function addAction($action, $callback, $priorty=10){
$this->actions[$action][] = [
'callback' => $callback,
'priorty' => $priorty
];
}
public function doAction($action, ...$args=[]){
if(!isset($this->actions[$action])) return;
usort($this->actions[$action], function($a,$b){
return $a['priorty'] <=> $b['priorty'];
});
foreach($this->actions[$action] as $action){
call_user_func_array($action['callback'], $args);
}
}
}
$mediator = mediator::getInstance();
//Testing
function bar($arg1, $arg2){
echo $arg1." ".$arg2."\n\n";
}
//callback using a standard function
$mediator->addAction('foo', 'bar');
//callback with a closure
$mediator->addAction('foo', function($arg1, $arg2){
echo $arg1." ".$arg2."\n\n";
});
class foo{
function bar($arg1, $arg2){
echo $arg1." ".$arg2."\n\n";
}
static function sbar($arg1, $arg2){
echo "static ".$arg1." ".$arg2."\n\n";
}
}
//callback with obj and method
$mediator->addAction('foo', [new foo, 'bar']);
//static callback with class name and method
$mediator->addAction('foo', ['foo', 'sbar'], 1);
//execute the hook (with arguments)
$mediator->doAction('foo', "bar", "baz");
输出
static bar baz
bar baz
bar baz
bar baz
请注意,我使用了一些特定于以下内容的快捷方式:
- PHPv5.6
...
可变参数,(不确定拼写是否正确)
但它基本上将参数包装在一个数组中(或解包,取决于它的使用方式)。如果您不在 5.6 或更高版本上(您应该在 7 上),但您可以这样做:
public function doAction($action, $args=[]){
$args = func_get_args();
$action = array_shift($args);
//...
}
基本上我们正在接受所有参数(在第一个之后)并将它们传递给call_user_func_array
. 使用...
just 更容易做到这一点。
- PHPv7+
<=>
宇宙飞船。
这是一个新的比较运算符,它返回 a<b=-1
a==b=0
anda>b=1
所以它只是将搜索排序处理得更干净一点:
usort($this->actions[$action], function($a,$b){
return $a['priorty'] <=> $b['priorty'];
});
//functionally the same as
usort($this->actions[$action], function($a,$b){
if($a['priorty'] == $b['priorty'])return 0;
return $a['priorty'] > $b['priorty'] ? 1 : -1;
});
这也是一个“单例”,因为它使事件系统的事情变得更容易。这是一个一次只能加载一个实例的类。你不能打电话new mediator
而不是打电话mediator::getInstance()
。因为回调存储在类中,如果你有不同的实例,你的回调将不存在。现在我们可以传递$mediator
对象,甚至可以将其设为“全局”,但我们也可以将其设为单例。
另请注意,我是$mediator->addAction('foo', ['foo', 'sbar'], 1);
最后注册的,但由于优先级为 1 和排序,它首先运行...
但是,是的,这就是您可以做的实现的“基本”方式并拥有一些功能。
就 WordPress 而言,过滤器会返回,而操作不会。这确实是主要区别。
即使是短代码和排队脚本也没有什么不同。
最后我会留给你这个:
在软件工程中,中介者模式定义了一个对象,该对象封装了一组对象如何交互。这种模式被认为是一种行为模式,因为它可以改变程序的运行行为。
通常一个程序由大量的类组成。逻辑和计算分布在这些类中。然而,随着更多类被添加到程序中,尤其是在维护和/或重构期间,这些类之间的通信问题可能会变得更加复杂。这使得程序更难阅读和维护。此外,更改程序可能会变得困难,因为任何更改都可能影响其他几个类中的代码。
使用中介者模式,对象之间的通信被封装在中介者对象中。对象不再直接相互通信,而是通过中介进行通信。这减少了通信对象之间的依赖关系,从而减少了耦合。
推荐阅读
- git - 防止文件被其他分支跟踪
- python - QtGui.QDialog : 'module' 对象没有属性 'QDialog' | Python2.7
- jackson - 使用 RestTemplate.postForObject(.....) 将 rest 服务的字符串响应的 xml 列表自动映射到相应的 java 对象
- python - python错误不确定是错误还是代码问题
- c++ - 如何减少 Lambda 过多的堆栈使用
- javascript - AngularJS 中的语音识别解决方案
- c - 使用 C 预处理器实现 if-else
- solr - 使用 solr 端点创建 CloudSolrClient
- java - 返回值分配问题(对于原始数据类型)
- java-8 - 在 java 8 中将 Collection(java.util.Collection) 转换为 Observable(io.reactivex.Observable)