web-dev-qa-db-ja.com

add_actionはクラスを参照します

'add_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_actionを通してクラスコンストラクターを実行するだけでいいのですが。ボールを転がすために必要なのはこれだけです。

34
Matthew Ruddy

いいえ、直接ではなく、フックを介してクラスを「初期化」またはインスタンス化することはできません。いくつかの追加コードが常に必要とされます(そしてあなた自身のためにワームの缶を開いているので、それをすることができるのは望ましいことではありません)。

これを行うより良い方法は次のとおりです。

class MyClass {
     function __construct() {
          add_action( 'admin_init',array( $this, 'getStuffDone' ) );
     }
     function getStuffDone() {
          // .. This is where stuff gets done ..
     }
}
$var = new MyClass();

もちろん、一般的な場合に合わせて単純化するためにインターフェースクラスを作成することもできます。

class IGetStuffDone {
    function IGetStuffDone(){
        add_action( 'admin_init',array( $this, 'getStuffDone' ) );
    }
    public abstract function getStuffDone();
}

インターフェースとして、このタイプのオブジェクトを直接作成することはできませんが、サブクラスを作成することもできます。

class CDoingThings extends IGetStuffDone {
    function getStuffDone(){
        // doing things
    }
}
$var = new CDoingThings();

これは自動的にすべてのフックを追加します。サブクラスで行われていることを正確に定義してから作成するだけです。

コンストラクタについて

フック関数としてコンストラクターを追加することはしません。これは良くない習慣で、たくさんの珍しい出来事を引き起こす可能性があります。またほとんどの言語でコンストラクタはインスタンス化されているオブジェクトを返すので、あなたのフックがフィルタのように何かを返す必要があるなら、それはあなたが望むようにフィルタされた変数を返さないでしょう。

コンストラクタやデストラクタを呼び出すことは、あなたがどの言語を使っていようと、非常に、非常に、非常に悪いプログラミング習慣であり、 決して 実行されるべきではありません。

コンストラクタは、実際の作業用ではなく、使用可能な状態に初期化するために、オブジェクトも構成する必要があります。オブジェクトによって行われる作業は、別の機能に含まれるべきです。

静的クラスメソッドで、インスタンス化/初期化をまったく必要としない

クラスメソッドが静的クラスメソッドの場合は、以下に示すように、クラスの名前を$thisではなく引用符で囲むことができます。

class MyClass {
     public static function getStuffDone() {
          // .. This is where stuff gets done ..
     }
}
add_action( 'admin_init', array('MyClass','getStuffDone' ) );

クロージャとPHP 5.3

残念ながら、新しいクラスを作成する行を避けることはできません。それをスキップする唯一の他の解決策は、まだその行を持ち、PHP 5.3+を必要とするボイラープレートコードを含むでしょう。

add_action('admin_init',function(){
    $var = new MyClass();
    $var->getStuffDone();
});

どの時点でクラスを飛ばして関数を使うだけでもかまいません。

add_action('admin_init',function(){
    // do stuff
});

しかし、匿名関数のスペクターが導入されました。 remove_actionを使用して上記のアクションを削除する方法はありません、そしてこれは他の人々のコードで作業しなければならない開発者にとって大きな苦痛を引き起こす可能性があり、また引き起こします。

アンパサンドについて

あなたは以下のようにアクションが使われるのを見るかもしれません:

add_action( &$this, 'getStuffDone' );

これは悪いです 。オブジェクトが参照としてではなく値として渡されたとき、&がPHP 4に追加されました。 PHP 4は10年以上前のもので、長い間WordPressでサポートされていません。

理由はありません フックやフィルタを追加するときに&thisを使用するため、参照を削除しても問題は発生せず、また将来のバージョンのPHPとの互換性も向上する可能性があります。

代わりにこれを使ってください。

add_action( $this, 'getStuffDone' );
63
Tom J Nowell

サンプルクラス

ノート:

  • 一度だけ授業を開始してください。
    • 優先度0で呼び出すので、後でデフォルトの優先度で同じフックを使用できます。
    • 2回呼び出さないように! class_existsでラップして、init呼び出し側を内側に配置します。
  • init関数とクラスvarをstaticにする
  • クラスnew selfを呼び出すときに、initの内側からコンストラクターを呼び出します。

これが例です

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;

Php 5+

ください &を省略してください。私たちはすでにphp4を超えています。 :)

10
kaiser
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();
}
2
Zakir Sajib

最初に をロードしなくても、クラス内でイベントを発生させることができます。クラス全体を前もってロードするのではなく、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リクエストでオブジェクトをトリガーするだけです。

0
John Reid

一般的に、フックにclass全体を追加することはありません。 add_action()/add_filter()フックは、コールバックfunctionsを期待します。これはcanクラス内から参照されます。

クラス内にinit()関数があり、WordPress initフックにフックするとします。

add_action()呼び出しinsideをクラスに追加し、次のようにコールバックを識別します。

add_action( 'init', array( $this, 'init' ) );

(注:クラスは適切に名前空間化されていると想定しています;それ以外の場合は、コールバック関数の名前空間化を必ず行ってください。)

0
Chip Bennett

インスタンス化されたオブジェクトの代わりにクラス名を渡すことでそれを実行できるはずです。

add_action( 'init', array( 'MyClass', '__construct' ) );

(理論的には、あなたの他の解決策もうまくいくはずです

$var = new MyClass();
add_action( 'admin_init', array( $var, '__construct' ) );

それがなぜそうではないのか頭からはっきりしない。あなたが参照で呼ばないならば、多分?)

0
Boone Gorges

これは私のために働く:

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

add_action('foo_bar', array('foo', 'bar'));
0
Jonathan