Existe-t-il une documentation quelque part qui explique quel est le cycle de vie des plugins?
Je commence un nouveau plugin avec le style OOP, et je viens de découvrir que ma classe principale est instanciée beaucoup (grâce à Xdebug et Netbeans).
Je me demande pourquoi, et cela me gêne parce que j'instancie un objet Dropbox-API, et je ne pensais vraiment pas que WordPress instillerait autant que ma classe principale.
Je n'ai rien trouvé concernant le cycle de vie des plugins dans le Codex ni sur Google.
Je commence un nouveau plugin avec le style OOP
Que signifie "style POO" pour vous? Enveloppant toutes vos fonctions avec une déclaration de classe? Alors tu le fais mal. Vous avez mal utilisé la classe comme espace de noms.
et je viens de découvrir que ma classe principale est beaucoup instanciée
Hein?
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(); } );
Essayez-le et comptez le nombre de fichiers créés. Si je l'essaie, il y a un fichier créé pour chaque demande de page. Cela signifie qu’une seule instance de la classe Foo pour chaque demande de page.
Essayons un appel d'action
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(); } );
Si je regarde dans mon répertoire wp-content, j'ai trouvé deux fichiers. Pas plus. Un fichier est créé lors de la création de l'instance de classe. Et l'un est créé lorsque l'appel à l'action est terminé.
OK, faisons des choses stupides avec notre instance. Supprimez la add_action( 'plugins_loaded', .. )
et ajoutez ce code à la place:
function bar( $foo ) {
$baz = $foo;
return $baz;
}
$f = new Foo();
$GLOBALS['foo'] = $f;
$f2 = $f;
$f3 = &$f;
$f4 = bar( $f2 );
$f5 = bar( $f3 );
Combien de fichiers attendez-vous? J'attends deux. Une du constructeur, une de la méthode.
Une nouvelle instance est créée uniquement lorsque l'opérateur new
est utilisé.
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 );
Maintenant, je compte quatre fichiers. Deux du constructeur et deux de la méthode. En effet, WordPress inclut d’abord le plug-in, puis le hook d’action plugins_loaded
.
La meilleure pratique consiste à utiliser l'action hook plugins_loaded
au lieu de créer une instance hors d'une fonction, car si le fichier de plug-in est inclus n'importe où (par exemple dans un autre fichier de votre plug-in), une nouvelle instance de la classe est créée chaque fois que le fichier est inclus. . L'action hook plugins_loaded
n'est effectuée qu'une fois pour chaque demande de page.
Ce qui pourrait arriver, c’est que vous transmettiez une copie de votre classe à un filtre ou à une action. Par exemple, si vous souhaitez modifier directement les variables de classe dans un hook ou un filtre, vous devez également passer le hook par référence.
add_action("some_action",array(&$this,"somefunction"))
au lieu de
add_action("some_action",array($this,"somefunction"))
Comme mentionné par bainternet, vous pouvez également utiliser un modèle singleton pour vous assurer qu'un objet spécifique n'est instancié qu'une seule fois (les appels suivants renvoient la référence à cet objet).
Vous pouvez également envisager de rendre certaines fonctions statiques (en leur donnant le mot-clé static. Cela est généralement utilisé pour les fonctions de type "helper" qui n'interagissent pas avec le reste de la classe. Les méthodes statiques peuvent être appelées sans instanciation de classe.
Vous pouvez également transmettre des fonctions statiques à une action/un filtre:
add_action("some_action",array("ClassName","Method"))
J'ai également vérifié http://codex.wordpress.org/Plugin_API/Action_Reference et constaté que les plug-ins ne peuvent être chargés qu'à deux étapes de la requête (muplugins_loaded et plugins_loaded).