首页 > 解决方案 > wordpress 如何制作动作/过滤器挂钩?(在其功能中附加您的功能)

问题描述

我对 Wordpress 使用什么概念来创建他们拥有的很棒的功能感兴趣:动作和过滤器。

有谁知道他们是如何工作的,以及如何在任何非 wordpress 应用程序/项目中创建类似的功能?

PS 只是想再澄清一下,以防万一,我知道如何在 wordpress 中使用它们,我对它们的实际工作方式很感兴趣。

谢谢!

标签: phpwordpress

解决方案


像这样的东西:

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=0anda>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 而言,过滤器会返回,而操作不会。这确实是主要区别。

即使是短代码和排队脚本也没有什么不同。

最后我会留给你这个:

在软件工程中,中介者模式定义了一个对象,该对象封装了一组对象如何交互。这种模式被认为是一种行为模式,因为它可以改变程序的运行行为。

通常一个程序由大量的类组成。逻辑和计算分布在这些类中。然而,随着更多类被添加到程序中,尤其是在维护和/或重构期间,这些类之间的通信问题可能会变得更加复杂。这使得程序更难阅读和维护。此外,更改程序可能会变得困难,因为任何更改都可能影响其他几个类中的代码。

使用中介者模式,对象之间的通信被封装在中介者对象中。对象不再直接相互通信,而是通过中介进行通信。这减少了通信对象之间的依赖关系,从而减少了耦合。


推荐阅读