add_actionはクラスを参照します
7 回答
- 投票
-
- 2012-04-05
いいえ、直接ではなく、フックを介してクラスを「初期化」またはインスタンス化することはできません.いくつかの追加のコードが常に必要です(そして、自分でワームの缶を開いているので、それができることは望ましいことではありません.
これを行うためのより良い方法は次のとおりです:
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();
その後、すべてのフックが自動的に追加されます.サブクラスで何が行われているのかを正確に定義して、それを作成するだけです!
コンストラクターについて
コンストラクターをフック関数として追加しないのは悪い習慣であり、多くの異常なイベントを引き起こす可能性があります.また、ほとんどの言語では、コンストラクターはインスタンス化されているオブジェクトを返すため、フックがフィルターのようなものを返す必要がある場合、フィルターされた変数は必要に応じて返されませんが、代わりにクラスオブジェクトが返されます.
>コンストラクタまたはデストラクタを直接呼び出すことは、使用している言語に関係なく、非常に、非常に、非常に悪いプログラミング手法であり、絶対に実行しないでください.
コンストラクターは、実際の作業ではなく、オブジェクトを使用できるように初期化するために、オブジェクトも作成する必要があります.オブジェクトによって実行される作業は、別の関数で行う必要があります.
静的クラスメソッドであり、インスタンス化/初期化する必要はまったくありません
クラスメソッドが静的クラスメソッドの場合、以下に示すように、
$this
ではなく、クラスの名前を引用符で囲むことができます.class MyClass { public static function getStuffDone() { // .. This is where stuff gets done .. } } add_action( 'admin_init', [ __NAMESPACE__ . '\MyClass','getStuffDone' ] );
クラスが名前空間内にある場合に必要な
__NAMESPACE__
の使用に注意してください.閉鎖
残念ながら、新しいクラスを作成する行を避けることはできません.それをスキップする他の唯一の解決策は、まだその行を持っているボイラープレートコードを含みます.例:
add_action( 'admin_init', function() { $var = new MyClass(); $var->getStuffDone(); } );
その時点で、クラスをスキップして、関数を使用することもできます:
add_action( 'admin_init', function() { // do stuff } );
ただし、匿名関数のスペクターを導入したことを忘れないでください.
remove_action
を使用して上記のアクションを削除する方法はありません.これは、他の人のコードを使用する必要がある開発者にとって大きな苦痛を引き起こす可能性があります.アンパサンドについて
次のように使用されるアクションが表示される場合があります:
array( &$this, 'getStuffDone' )
これは悪いです.
&
は、オブジェクトが参照としてではなく値として渡されたときにPHP4で追加されました. PHP 4は10年以上前のものであり、WordPressでは非常に長い間サポートされていません.フックとフィルターを追加するときに
&this
を使用する理由はありません.参照を削除しても問題は発生せず、将来のバージョンとの互換性も向上する可能性があります. PHP代わりにこれを使用してください:
[ $this, 'getStuffDone' ]
No, you cannot 'initialise' or instantiate the class through a hook, not directly. Some additional code is always required ( and it is not a desirable thing to be able to do that, as you're opening a can of worms for yourself.
Here is a better way of doing it:
class MyClass { function __construct() { add_action( 'admin_init', [ $this, 'getStuffDone' ] ); } function getStuffDone() { // .. This is where stuff gets done .. } } $var = new MyClass();
Of course one could create an interface class to simplify it for the general case even further:
class IGetStuffDone { function IGetStuffDone(){ add_action( 'admin_init', [ $this, 'getStuffDone' ] ); } public abstract function getStuffDone(); }
Note that as an interface, you can't create an object of this type directly, but you could create a sub-class, letting you say:
class CDoingThings extends IGetStuffDone { function getStuffDone(){ // doing things } } $var = new CDoingThings();
Which would then automatically add all the hooks, you just need to define what exactly is being done in a subclass and then create it!
On Constructors
I wouldn't add a constructor as a hook function, it's bad practice, and can lead ot a lot of unusual events. Also in most languages a constructor returns the object that is being instantiated, so if your hook needs to return something like in a filter, it will not return the filtered variable as you want, but instead it will return the class object.
Directly calling a constructor or a destructor is very, very, very bad programming practice, no matter which language you're in, and should never be done.
Constructors should also construct objects, to initialise them ready for use, not for actual work. Work to be done by the object should be in a separate function.
Static class methods, and not needing to instantiate/initialise at all
If your class method is a static class method, you can pass the name of the class in quotes rather than
$this
as shown below:class MyClass { public static function getStuffDone() { // .. This is where stuff gets done .. } } add_action( 'admin_init', [ __NAMESPACE__ . '\MyClass','getStuffDone' ] );
Note the use of
__NAMESPACE__
which is required if your class is inside a namespace.Closures
Sadly you cannot avoid the line creating the new class. The only other solution to skipping it would involve boiler plate code that still has that line e.g.:
add_action( 'admin_init', function() { $var = new MyClass(); $var->getStuffDone(); } );
At which point you may as well skip the class, and just use a function:
add_action( 'admin_init', function() { // do stuff } );
But keep in mind you have now introduced the spectre of anonymous functions. There is no way to remove the above action using
remove_action
, and this can and does cause great pain for developers who have to work with other peoples code.On Ampersands
You may see actions used like this:
array( &$this, 'getStuffDone' )
This is bad.
&
was added back in PHP 4 when objects were passed as values, not as references. PHP 4 is more than a decade old, and hasn't been supported by WordPress in a very long time.There is no reason to use
&this
when adding hooks and filters, and removing the reference will cause no issues, and may even improve compatibility with future versions of PHPUse this instead:
[ $this, 'getStuffDone' ]
-
OK.そのすべてからありがとう.本当にたくさん学びました.私は今、クラスベースのPHPに慣れてきました.これは私がやったことであり、うまくいきますが、それが悪い習慣/間違っているかどうか教えていただけますか?クラス自体の中で、静的関数の中でクラスを開始しました.次に、add_actionで静的関数を参照しました.このリンクを参照してください:http://pastebin.com/0idyPwwYOk. Thank you from all of that; really learnt quite a bit. I'm really only getting comfortable in class based PHP now. This is what I have done, and it works, but could you tell me if it is bad practice/incorrect in any way? I've initiated the class inside a static function, within the class itself. Then referenced the static function in the add_action. See this link: http://pastebin.com/0idyPwwY
- 0
- 2012-04-05
- Matthew Ruddy
-
はい、そうすることができます.変数名として `$ class`を使用することは避けられますが、それらの単語は予約される傾向があります.グローバルスコープで `$ x=new Y();`に似たようなことを言わないようにし、必要のないところに複雑さを加えていると思います.書かれるコードの量を減らすためのあなたの試みは、より多くのコードを書くことを含みました!yes you could do it that way, though I could avoid using `$class` as your variable name, those words tend to be reserved. I think you're going way out of your way to avoid saying something similar to `$x = new Y();` in the global scope, and you're adding complexity where none is necessary. Your attempt to reduce the amount of code written has involved writing more code!
- 0
- 2012-04-05
- Tom J Nowell
-
上記のすべての場合において、クラスよりも関数を使用する方がよいことを指摘しておきます.そのクラスはとにかく破棄され、同じ目的を果たすからです.それは資源の無駄です.オブジェクトの作成と破棄にはコストがかかり、オブジェクトの数が少なく、長持ちすることを忘れないでください.I'd point out in all of the above cases, you would be better off using a function rather than a class, as that class will be discarded anyway and serves the same purpose. It's a waste of resources. Remember, there is a cost to creating and destroying an object, you want few objects, and you want them to be long lived
- 0
- 2012-04-05
- Tom J Nowell
-
いい視点ね.私がそれを見ていた方法を変えました.代わりに、余分なコードを避けて、グローバルスコープで呼び出すと思います.Good point. Changed the way I've been looking at it. I think I'll call it in the global scope instead, avoiding the extra code.
- 0
- 2012-04-05
- Matthew Ruddy
-
クラスを名前空間に配置した場合は、それも追加する必要があります.そうしないと、add_action()/add_filter()がそれを検出しません-次のようになります: `` `add_action( 'admin_init'、array( 'MyNamespace \ MyClass'、 'getStuffDone')); `` `I would like to add that if you happen to have put your class in a namespace, you will have to add that too or add_action()/add_filter() won't find it - like this: ```add_action( 'admin_init', array('MyNamespace\MyClass','getStuffDone' ) );```
- 1
- 2018-04-27
- jschrab
-
- 2012-04-05
サンプルクラス
注:
- クラスを1回だけ初期化する
- 優先度0を呼び出すと、後でデフォルトの優先度で同じフックを使用できます
- <コード>でまとめてください! class_exists を使用して、2回呼び出さないようにし、init呼び出し元を内部に配置します
-
init
関数とクラスvarstatic
を作成します
- クラス
new self
を呼び出すときに、init内からコンストラクターを呼び出します.
ここに例があります
if(!class_exists( 'WPSESampleClass')) {{ //デフォルト=10としてクラス内に優先度が追加されないように、優先度0でクラスを初期化します add_action( 'init'、array( 'WPSESampleClass'、 'init')、0); クラスWPSESampleClass {{ /** *クラスオブジェクト */ staticprivate $ class=null; パブリック静的関数init() {{ if(null===self :: $ class) 自己:: $ class=新しい自己; 自己を返す:: $ class; } パブリック関数__construct() {{ //アクション呼び出しの追加などを行います: add_action( 'init'、array($this、 'cb_fn_name')); } パブリック関数cb_fn_name() {{ //何かをする } }//ENDクラスWPSESampleClass }//endif;
PHP 5+
お願い、
&amp;
は省略してください.私たちはすでにphp4を超えています. :)Example class
Notes:
- Init the class only once
- Call on priority 0, so you can use the same hook with the default priority later
- Wrap it up in a
! class_exists
to avoid calling it twice and place the init caller inside
- Make the
init
function and the class varstatic
- Call the constructor from inside your init, when you call the class
new self
.
Here's an example
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+
Please, leave the
&
out. We're already beyond php4. :) -
- 2018-03-04
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(); }
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(); }
-
** [編集]あなたの答え**と説明を追加してください:**なぜ**それが問題を解決できるのでしょうか?Please **[edit] your answer**, and add an explanation: **why** could that solve the problem?
- 0
- 2018-03-04
- fuxia
-
-
- 2012-04-05
一般的に言って、クラス全体をフックに追加することはありません.
add_action()
/add_filter()
フックは、コールバック関数 を予期します.これは、内から参照できます.クラス.クラス内に
init()
関数があり、WordPressのinit
フックにフックしたいとします.add_action()
呼び出しをクラス内に配置し、次のようにコールバックを識別します.add_action( 'init', array( $this, 'init' ) );
(注:クラスには適切な名前空間が付けられていると想定しています.それ以外の場合は、必ずコールバック関数に名前空間を付けてください.)
Generally speaking, you wouldn't add an entire class to a hook. The
add_action()
/add_filter()
hooks expect callback functions, which can be referenced from within a class.Let's say that you have an
init()
function inside your class, that you want to hook into the WordPressinit
hook.Put your
add_action()
call inside your class, and then identify the callback like so:add_action( 'init', array( $this, 'init' ) );
(Note: I'm assuming your class is properly namespaced; otherwise, be sure to namespace your callback functions.)
-
現在のクラスがまだ開始されていない場合はどうなりますか?add_actionを使用して実際に開始しようとしたので、$ var=new MyClass();を追加する必要はありません.事前に他の場所で.What about if the current class hasn't already been initiated? I was trying to use add_action to actually initiate, so I don't have to add $var = new MyClass(); beforehand elsewhere.
- 0
- 2012-04-05
- Matthew Ruddy
-
`init`(または必要な場所)でクラスをインスタンス化するためのコールバックを作成するだけではいけませんか?Can you not just write a callback to instantiate your class at `init` (or wherever you need it)?
- 0
- 2012-04-05
- Chip Bennett
-
- 2012-04-05
インスタンス化されたオブジェクトの代わりにクラス名を渡すことでそれを実行できるはずです:
add_action( 'init', array( 'MyClass', '__construct' ) );
(理論的には、他のソリューションも機能するはずです
$var = new MyClass(); add_action( 'admin_init', array( $var, '__construct' ) );
なぜそうならないのかわからない.参照で電話しない場合はどうでしょうか?)
You should be able to do it by passing the class name instead of the instantiated object:
add_action( 'init', array( 'MyClass', '__construct' ) );
(In theory, your other solution should work too
$var = new MyClass(); add_action( 'admin_init', array( $var, '__construct' ) );
Not sure off the head why it doesn't. Maybe if you don't call by reference?)
-
最初のものは機能しません.ページを空白にするだけです.2番目は機能しますが、クラスが最初の行で開始されているためです.クラスはすでに開始されているため、アクションを追加する目的が無効になります.しかし、それは私がやろうとしていること、つまりアクションを通してクラスを開始することをしません.私が取り組んでいる実際のコードでは、アクションは「admin_init」ではなく、別のクラス内のカスタムアクションです.他のクラスのアクションが存在しない場合、関数「MyClass」を開始したくありません.何かが足りない場合は申し訳ありません.私が行くにつれて学ぶFirst one doesn't work. Just makes the page go blank. The second works, but only because the class has been initiated in the first line. It sort of defeats the purpose of adding the action, because the class has already been initiated. But it doesn't do what I'm trying to do, which is initiate the class through the action. In the actual code I'm working on, the action isn't 'admin_init' but a custom action within another class. I don't want the function 'MyClass' to be initiated if the action in the other class isn't there. Sorry if I'm missing something; learning as I go
- 0
- 2012-04-05
- Matthew Ruddy
-
ええ、私は間違っていました.これは、静的な `init`メソッドを呼び出している場合にのみ機能します.http://wordpress.stackexchange.com/a/48093/14052を参照してくださいYeah, I was wrong. That only works if you're calling a static `init` method. See http://wordpress.stackexchange.com/a/48093/14052
- 0
- 2012-04-05
- Boone Gorges
-
- 2014-12-22
クラスでイベントをトリガーできます.最初にロードする必要はありません.これは、クラス全体を事前にロードしたくないが、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();
これはカイザーの答えを非常に単純化したものですが、動作を簡単に示しています.このスタイルを初めて見る人には便利かもしれません.
必要に応じて、他のメソッドでもオブジェクトを開始できます.私は個人的にこのメソッドを使用して、プラグインのオプション部分がスクリプトをキューに入れることを許可していますが、AJAXリクエストでオブジェクトをトリガーするだけです.
You can trigger events in your class without the need to load it initially. This is handy if you don't want to load the full class up front, but need to access the WordPress filters and actions.
Here's a very simple example
<?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();
This is a very simplified version of Kaiser's answer but shows in simple terms the behaviour. Might be handy for those looking at this style for the first time.
Other methods can still initiate the object if required. I'm personally using this method to allow optional parts of my plugin to enqueue scripts, but only triggering the object on an AJAX request.
'add_action'で関数の代わりにクラスを参照することは可能ですか?それを理解できないようです.これは、問題の関数の基本的な例です.
そうですね、それはうまくいきません.私も試しました:
そして:
また:
クラスをロードする別の関数を作成せずにこれを実行できる方法はありますか?add_actionを介してクラスコンストラクターを実行できるようにしたいと思います.ボールを転がすためにロードする必要があるのはこれだけです.