プラグインのライフサイクルは何かを説明する文書がどこかにありますか?
私はOOPスタイルの新しいプラグインを始めました、そして私のメインクラスがインスタンス化されていることを知りました たくさん (XdebugとNetbeansのおかげで)。
どうしてだろうか、そしてDropbox-APIオブジェクトをインスタンス化しているのが厄介だし、WordPressがメインクラスをそれほどインスタンス化するとは思わなかった。
CodexにもGoogleにもプラグインのライフサイクルに関連するものはありません。
OOPスタイルで新しいプラグインを始めています
「OOPスタイル」とはどういう意味ですか?すべての関数をクラスステートメントでラップしますか?それからあなたはそれを間違ってやっています。名前空間としてクラスを誤用します。
そして、私はメインクラスがたくさんインスタンス化されていることを知りました。
え?
class Foo
{
public function __construct() {
// assuming your wp-content dir is writeable
$filename = sprintf( WP_CONTENT_DIR . '/dummyfile-%d.txt', time() );
$handle = fopen( $filename, 'w' );
if ( $handle ) {
fputs( $handle, '-' );
fclose( $handle );
}
}
}
add_action( 'plugins_loaded', function() { new Foo(); } );
試してみて、作成されたファイルの数を数えてください。試してみると、ページリクエストごとに one ファイルが作成されます。これは、各ページ要求に対してFooクラスの1つの instance だけが意味されます。
アクションコールをしてみましょう
class Foo
{
public function __construct() {
$this->write_file( 'in_constructor' );
add_action( 'init', array( $this, 'action_test' ), 10, 0 );
}
public function action_test() {
$this->write_file( 'in_method_with_action_call' );
}
public function write_file( $filename ) {
// assuming your wp-content dir is writeable
$counter = 1;
$fname = sprintf( WP_CONTENT_DIR . '/%s-%d.txt', $filename, $counter );
if ( file_exists( $fname ) ) {
preg_match( '/(\d)\.txt/is', $fname, $match );
if ( isset( $match[1] ) ) {
$counter = (int) $match[1] + 1;
$fname = sprintf( WP_CONTENT_DIR . '/%s-%d.txt', $filename, $counter );
}
}
$handle = fopen( $fname, 'a+' );
if ( $handle ) {
fputs( $handle, '-' );
fclose( $handle );
} else {
throw new Exception( "Cannot open file {$fname} for writing" );
}
}
}
add_action( 'plugins_loaded', function() { new Foo(); } );
Wp-contentディレクトリを見ると、2つのファイルが見つかりました。もういや。クラスインスタンスの作成時に1つのファイルが作成されます。そして、アクション呼び出しが完了したときに作成されます。
それでは、私たちのインスタンスでばかげたことをしましょう。 add_action( 'plugins_loaded', .. )
を削除して、代わりにこのコードを追加してください:
function bar( $foo ) {
$baz = $foo;
return $baz;
}
$f = new Foo();
$GLOBALS['foo'] = $f;
$f2 = $f;
$f3 = &$f;
$f4 = bar( $f2 );
$f5 = bar( $f3 );
いくつのファイルを期待しますか。 2つ期待しています。一つはコンストラクタから、もう一つはメソッドからです。
new
演算子が使用されている場合にのみ、新しいインスタンスが作成されます。
add_action( 'plugins_loaded', 'new_foo', 10, 0 );
function new_foo() {
// first instance
new Foo();
}
function bar( $foo ) {
$baz = $foo;
return $baz;
}
// second instance here!!
$f = new Foo();
$GLOBALS['foo'] = $f;
$f2 = $f;
$f3 = &$f;
$f4 = bar( $f2 );
$f5 = bar( $f3 );
今私は4つのファイルを数える。 2つはコンストラクタから、もう2つはメソッドからです。これはWordPressが最初にプラグインをインクルードしてからアクションフックplugins_loaded
を実行するためです。
ベストプラクティスは、関数からインスタンスを作成するのではなく、アクションフックplugins_loaded
を使用することです。プラグインファイルがどこかに含まれていると(例えば、あなたのプラグインの別のファイル) 。アクションフックplugins_loaded
は各ページリクエストに対して一度だけ行われます。
起こるかもしれないことはあなたがあなたのクラスのコピーをフィルタまたはアクションに渡すことです。たとえば、フックまたはフィルタ内でクラス変数を直接変更したい場合は、参照によってフックを渡す必要があります。
add_action("some_action",array(&$this,"somefunction"))
の代わりに
add_action("some_action",array($this,"somefunction"))
Bainternetが述べているように、特定のオブジェクトが一度だけインスタンス化されることを確実にするためにシングルトンパターンを使うこともできます(それ以降の呼び出しはそのオブジェクトへの参照を返します)。
また、いくつかの関数をstaticにすることを検討することもできます(staticキーワードを与えることによって)。これは通常、クラスの他の部分と対話しない「ヘルパー」のような関数に対して行われます。
静的関数をアクション/フィルタに渡すこともできます。
add_action("some_action",array("ClassName","Method"))
また、 http://codex.wordpress.org/Plugin_API/Action_Reference をチェックしたところ、プラグインはリクエストの2段階でしかロードできないことがわかりました(muplugins_loadedとplugins_loaded)。