如何在匿名回调中使用OOP时取消WordPress的操作/过滤器

时间:2014-07-23 作者:Yoga

我找到的大多数wordpress插件是functions based, 例如,官方akismet 插件

function akismet_init() {
    global $wpcom_api_key, $akismet_api_host, $akismet_api_port;


    // ...
}
add_action(\'init\', \'akismet_init\');

There are a few issues with this approach:

<你不能在函数之间共享状态,因此你必须使用全局变量进行难以进行的单元测试,也就是说,没有办法模拟。我最初的尝试是包装成一个对象,例如akismet.php

class Akismet {

    protected static $akismet_api_host;
    protected static $akismet_api_port;

    public function __construct()
    {
        add_action(\'init\', array($this, \'init\'));
    }

    public function init()
    {
       // Do my init here
    }
}

$GLOBALS[\'Akismet\'] = new Akismet();
然而,这种方法仍然存在一些问题

我需要将我的大多数方法作为公共方法来调用(这很糟糕)

  • 如果不使用匿名回调,就无法将变量传递到回调中(如果使用匿名回调,则无法使用remove\\u操作/remove\\u过滤器将其删除)
    • 例如。

      public function __construct()
      {
          $foo = \'bar\';
          add_action(\'init\', function() use ($foo) {
            echo $foo; // You can pass variable by using callback but you cannot this action later!
          });
      }
      
      那么,如何灵活地将变量传递到任何Wordpress的操作/过滤器中,同时保持稍后取消它们的灵活性呢?

    2 个回复
    SO网友:JMau

    一种方法是使用类和对象。考虑到可重用性、集体工作等因素,它的效率更高。如果你知道自己在做什么,我认为使用全局变量并不坏。

    所以我建议您使用OOP(面向对象编程),尤其是继承和多态性。

    SO网友:J.D.

    那么,如何灵活地将变量传递到任何Wordpress的操作/过滤器中,同时保持稍后取消它们的灵活性呢?

    您可以将函数指定给类的一个属性:

    public function __construct()
    {
        $foo = \'bar\';
    
        $this->init_func = function() use ( $foo ) {
            echo $foo;
        };
    
        add_action( \'init\', $this->init_func );
    }
    
    之后,您可以执行以下操作:

    remove_action( \'init\', $this->init_func );
    
    但请不要这样做

    我认为这会让测试成为一场噩梦。此外,您所在的类可以将要在函数中使用的值指定给属性:

    public function __construct()
    {
        $this->foo = \'bar\';
    
        add_action( \'init\', array( $this, \'init\' ) );
    }
    
    public function init()
    {
        echo $this->foo;
    }
    
    这就是课程的目的。:-)

    您似乎害怕使用公共类方法。为什么?您希望WordPress能够调用类的代码,因此它必须有一些公共API来支持这一点。PHP类提供public 方法,所以您最好使用它们,而不是试图重新发明轮子。:-)

    结束