Existe-t-il une documentation sur le cycle de vie des plugins?

11

Y a-t-il quelque part une documentation 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 beaucoup instanciée (grâce à Xdebug et Netbeans).
Je me demande pourquoi, et cela m'énerve parce que j'instancie un objet Dropbox-API, et je ne pensais vraiment pas que WordPress instancierait tellement ma classe principale.

Je n'ai rien trouvé concernant le cycle de vie des plugins dans le Codex ni sur Google.

RitonLaJoie
la source
Et ici, avez-vous cherché ici ? :)
brasofilo
20
YouPorn peut toujours définir votre classe comme un singleton stackoverflow.com/questions/203336/…
Bainternet
1
Merci. Je n'ai pas pensé aux «meilleures pratiques». J'ai lu beaucoup de choses sur le Codex, y compris les directives de codage mais ce n'est pas ici .. J'essaierai alors le singleton, mais quand même, je trouve étrange que le plugin php soit appelé plusieurs fois .. Non? Bainternet soyez prudent avec votre saisie
semi-
brasofilo, faire un singleton aiderait mais ne répond pas à la question qui est: pourquoi le code est-il exécuté plusieurs fois dans mon plugin? La classe OO dans l'URL que vous avez liée fait exactement ce que je fais
RitonLaJoie
2
Je devais juste attribuer +1 à la question. Juste pour le commentaire et les votes positifs: D
kaiser

Réponses:

3

Je commence un nouveau plugin avec le style OOP

Que signifie pour vous le «style OOP»? Envelopper toutes vos fonctions avec une instruction de classe? Ensuite, vous le faites mal. Vous utilisez mal la classe comme espace de noms.

et je viens de découvrir que ma classe principale est instanciée beaucoup

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'essaye, il y a un fichier créé pour chaque demande de page. Cela signifie, une seule instance de la classe Foo pour chaque demande de page.

Essayons un appel à l'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 un est créé lorsque l'appel à l'action est terminé.

OK, faisons des choses stupides avec notre instance. Supprimez le 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'en attends deux. Un du constructeur, un de la méthode.

Une nouvelle instance n'est créée que lorsque l' newopérateur 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 plugin, puis effectue le crochet d'action plugins_loaded.

La meilleure pratique consiste à utiliser le hook d'action plugins_loadedau lieu de créer une instance à partir d'une fonction car, si le fichier du plugin est inclus n'importe où (par exemple dans un autre fichier de votre plugin), une nouvelle instance de la classe est créée chaque fois que le fichier est inclus. Le hook d'action plugins_loadedn'est effectué qu'une seule fois pour chaque demande de page.

Ralf912
la source
0

Ce qui pourrait arriver, c'est que vous passez une copie de votre classe à un filtre ou une action. Par exemple, si vous souhaitez modifier directement les variables de classe à l'intérieur d'un hook ou d'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 fait 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 instancier une classe.

Vous pouvez également passer 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 plugins ne peuvent être chargés qu'à deux étapes de la demande (muplugins_loaded et plugins_loaded).

Arevico
la source
3
Lorsqu'un objet est envoyé par argument, retourné ou affecté à une autre variable, les différentes variables ne sont pas des alias: elles contiennent une copie de l'identifiant, qui pointe vers le même objet. du manuel PHP . Dans un appel ou un filtre d'action, la classe est envoyée comme argument. Depuis PHP5 il n'est pas nécessaire de le passer comme référence.
Ralf912
Je me tiens corrigé
Arevico