add_action reference a class

时间:2012-04-05 作者:Matthew Ruddy

是否可以在“add\\u action”中引用类而不是函数?似乎无法理解。这里只是有关函数的一个基本示例。

add_action( \'admin_init\', \'MyClass\' );
class MyClass {
     function __construct() {
          .. This is where stuff gets done ..
     }
}
所以是的,这不管用。我也尝试过:

$var = new MyClass();
add_action( \'admin_init\', array( &$var ) );
以及:

$var = new MyClass();
add_action( \'admin_init\', array( &$var, \'__construct\' ) );
而且:

add_action( \'admin_init\', \'MyClass::__construct\' );
我是否可以在不必创建加载类的单独函数的情况下执行此操作?我希望能够通过add\\u操作运行类构造函数。这就是让球滚动所需的全部负荷。

7 个回复
最合适的回答,由SO网友:Tom J Nowell 整理而成

不,不能通过钩子“初始化”或实例化类,不能直接。总是需要一些额外的代码(而且这不是一件理想的事情,因为你正在为自己打开一罐蠕虫。

以下是一种更好的方法:

class MyClass {
     function __construct() {
          add_action( \'admin_init\', [ $this, \'getStuffDone\' ] );
     }
     function getStuffDone() {
          // .. This is where stuff gets done ..
     }
}
$var = new MyClass();
当然,可以创建一个接口类来进一步简化一般情况下的接口类:

class IGetStuffDone {
    function IGetStuffDone(){
        add_action( \'admin_init\', [ $this, \'getStuffDone\' ] );
    }
    public abstract function getStuffDone();
}
请注意,作为接口,您不能直接创建这种类型的对象,但可以创建一个子类,可以这样说:

class CDoingThings extends IGetStuffDone {
    function getStuffDone(){
        // doing things
    }
}
$var = new CDoingThings();
这将自动添加所有挂钩,您只需定义子类中的具体操作,然后创建它!

On Constructors

我不会将构造函数添加为钩子函数,这是一种不好的做法,可能会导致很多不寻常的事件。此外,在大多数语言中,构造函数都会返回正在实例化的对象,因此,如果钩子需要返回类似于过滤器中的内容,它将不会返回所需的已过滤变量,而是返回class对象。

直接调用构造函数或析构函数是非常非常糟糕的编程实践,无论您使用哪种语言,也应该never 完成。

构造器还应该构造对象,以便初始化它们以供使用,而不是用于实际工作。对象要完成的工作应该在单独的函数中。

Static class methods, and not needing to instantiate/initialise at all

如果类方法是静态类方法,则可以在引号中传递类的名称,而不是$this 如下所示:

class MyClass {
    public static function getStuffDone() {
        // .. This is where stuff gets done ..
    }
}
add_action( \'admin_init\', [ __NAMESPACE__ . \'\\MyClass\',\'getStuffDone\' ] );
注意使用__NAMESPACE__ 如果您的类位于命名空间内,则需要使用该名称。

Closures

遗憾的是,您无法避免创建新类的这一行。跳过它的唯一其他解决方案将涉及仍有该行的锅炉板代码,例如:

add_action( \'admin_init\', function() {
    $var = new MyClass();
    $var->getStuffDone();
} );
此时,您可以跳过该类,只使用函数:

add_action( \'admin_init\', function() {
   // do stuff
} );
但请记住,您现在已经引入了匿名函数的幽灵。无法使用删除上述操作remove_action, 这可能而且确实会给那些不得不使用其他人代码的开发人员带来巨大的痛苦。

On Ampersands

您可能会看到这样使用的操作:

array( &$this, \'getStuffDone\' )
This is bad. & 是在PHP 4中添加的,当时对象是作为值传递的,而不是作为引用传递的。PHP 4已有十多年的历史,WordPress已经很长时间不支持它了。

no reason 使用&this 在添加挂钩和过滤器时,删除引用不会引起任何问题,甚至可能改善与PHP未来版本的兼容性

请改用此选项:

[ $this, \'getStuffDone\' ]

SO网友:kaiser

示例类注释:

仅初始化类一次,调用优先级为0的钩子,因此以后可以使用默认优先级的钩子! class_exists 要避免调用它两次,请将init调用者放在内部init 函数和类varstaticnew self.

if ( ! class_exists( \'WPSESampleClass\' ) )
{
    // Init the class on priority 0 to avoid adding priority inside the class as default = 10
    add_action( \'init\', array ( \'WPSESampleClass\', \'init\' ), 0 );

class WPSESampleClass
{
    /**
     * The Class Object
     */
    static private $class = null;

    public static function init()
    {
        if ( null === self::$class ) 
            self :: $class = new self;

        return self :: $class;
    }

    public function __construct()
    {
        // do stuff like add action calls:
        add_action( \'init\', array( $this, \'cb_fn_name\' ) );
    }

    public function cb_fn_name()
    {
        // do stuff 
    }
} // END Class WPSESampleClass

} // endif;
请离开& 出来我们已经超过了php4。:)

SO网友:Zakir Sajib
if (!class_exists("AllInOneWoo")){
    class AllInOneWoo {
        function __construct(){
            add_action(\'admin_menu\', array($this, \'all_in_one_woo\') );
        }
        function all_in_one_woo(){
            $page_title = \'All In One Woo\';
            $menu_title = \'All In One Woo\';
            $capability = \'manage_options\';
            $menu_slug  = \'all-in-one-woo-menu\';
            $function   = array($this, \'all_in_one_woo_menu\');
            $icon_url   = \'dashicons-media-code\';
            $position   = 59;

            add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position);
        }
        function all_in_one_woo_menu(){?>
            <div class="wrap">
                <h1><?php _e(\'All In One Woo\', \'all_in_one_woo\'); ?></h1>
            </div>
        <?php }
    }// end class
}// end if

if (class_exists("AllInOneWoo")){       
    $all_in_one_woo = new AllInOneWoo();
}
SO网友:John Reid

您可以在类中触发事件,而无需最初加载它。如果您不想预先加载整个类,但需要访问WordPress过滤器和操作,那么这很方便。

下面是一个非常简单的示例

<?php
class MyClass
{
    public static function init()
    {
        add_filter( \'the_content\', array(\'MyClass\', \'myMethod\') );
    }

    public static function myMethod($content)
    {
        $content = $content . \'Working without loading the object\';
    }
}

MyClass::init();
这是Kaiser答案的一个非常简化的版本,但用简单的术语显示了行为。对于那些第一次看到这种风格的人来说可能很方便。

如果需要,其他方法仍然可以启动对象。我个人使用此方法允许插件的可选部分将脚本排队,但仅在AJAX请求时触发对象。

SO网友:Jonathan

This works for me:

class foo
{
    public static function bar()
    {
        echo \'it works!\';
    }
}

add_action(\'foo_bar\', array(\'foo\', \'bar\'));
SO网友:Chip Bennett

一般来说,您不会将整个类添加到挂钩中。这个add_action()/add_filter() 钩子需要回调函数,可以从类中引用回调函数。

假设你有一个init() 类中的函数,您希望将其挂接到WordPress中init

把你的add_action() 在类中调用,然后像这样识别回调:

add_action( \'init\', array( $this, \'init\' ) );
(注意:我假设您的类具有正确的名称空间;否则,请确保为回调函数命名名称空间。)

SO网友:Boone Gorges

您应该能够通过传递类名而不是实例化对象来完成此操作:

add_action( \'init\', array( \'MyClass\', \'__construct\' ) );
(理论上,你的其他解决方案也应该奏效

$var = new MyClass();
add_action( \'admin_init\', array( $var, \'__construct\' ) );
不太清楚为什么没有。也许如果你不打电话给我的话?)

结束

相关推荐

Custom Post Row Actions

我偶然发现this question 在写这个问题的时候。我有一个问题是关于这个问题的。我发现你用的是get_delete_post_link 筛选为我的操作创建一个新的url(或一个类似的函数——在任何情况下,我都会将该函数与布尔值一起使用)。唯一的问题是,I don\'t know how to capture the event now. 考虑到我在谷歌上找不到很多关于行后操作的例子,我将不胜感激-/public function _wp_filter_get_delete_post_link( $