¿Existe una documentación del ciclo de vida del complemento?

11

¿Existe alguna documentación en algún lugar que explique cuál es el ciclo de vida de los complementos?

Estoy comenzando un nuevo complemento con estilo OOP, y acabo de descubrir que mi clase principal está siendo instanciada mucho (gracias a Xdebug y Netbeans).
Me pregunto por qué, y me molesta porque estoy instanciando un objeto de Dropbox-API, y realmente no pensé que WordPress simplemente instanciaría tanto a mi clase principal.

No he encontrado nada relacionado con el ciclo de vida de los complementos en el Codex ni en Google.

RitonLaJoie
fuente
Y aquí, ¿has buscado aquí ? :)
brasofilo
20
YouPorn siempre puede definir su clase como un singleton stackoverflow.com/questions/203336/…
Bainternet
1
Gracias. No pensé en las "mejores prácticas". Leí muchas cosas en el Codex, incluidas las Directrices de codificación, pero no está aquí. Intentaré el singleton entonces, pero aún así, me resulta extraño que el plugin php se llame varias veces ... ¿No? Bainternet ten cuidado con tu autocompletar :)
RitonLaJoie
brasofilo, hacer un singleton ayudaría pero no responde la pregunta que es: ¿por qué el código se ejecuta varias veces dentro de mi complemento? La clase OO en la URL que
vinculaste
2
Solo tenía que hacer +1 en la pregunta. Solo por el comentario y los votos a favor: D
kaiser

Respuestas:

3

Estoy comenzando un nuevo complemento con estilo OOP

¿Qué significa 'estilo OOP' para ti? ¿Envolviendo todas sus funciones con una declaración de clase? Entonces lo estás haciendo mal. Usas mal la clase como espacio de nombres.

y acabo de descubrir que mi clase principal está siendo instanciada mucho

¿Eh?

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(); } );

Pruébelo y cuente la cantidad de archivos creados. Si lo pruebo, hay un archivo creado para cada solicitud de página. Esto significa que solo una instancia de la clase Foo para cada solicitud de página.

Probemos una llamada a la acción

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 busco en mi directorio wp-content, encontré dos archivos. No más. Se crea un archivo cuando se crea la instancia de clase. Y se crea uno cuando finaliza la llamada a la acción.

Bien, hagamos algunas estupideces con nuestra instancia. Elimine add_action( 'plugins_loaded', .. )y agregue este código en su lugar:

function bar( $foo ) {

    $baz = $foo;
    return $baz;
}

$f = new Foo();
$GLOBALS['foo'] = $f;

$f2 = $f;
$f3 = &$f;

$f4 = bar( $f2 );
$f5 = bar( $f3 );

¿Cuántos archivos esperas? Espero dos. Uno del constructor, uno del método.

Se crea una nueva instancia solo cuando newse utiliza el operador.

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 );

Ahora cuento cuatro archivos. Dos del constructor y dos del método. Esto se debe a que WordPress primero incluye el complemento y luego realiza el gancho de acción plugins_loaded.

La mejor práctica es usar el gancho de acción en plugins_loadedlugar de crear una instancia a partir de una función porque, si el archivo de complemento se incluye en algún lugar (por ejemplo, en otro archivo de su complemento), se crea una nueva instancia de la clase cada vez que se incluye el archivo. El enlace de acción plugins_loadedse realiza solo una vez por cada solicitud de página.

Ralf912
fuente
0

Lo que podría suceder es que pase una copia de su clase a un filtro o acción. Por ejemplo, si desea modificar directamente las variables de clase dentro de un enlace o filtro, también debe pasar el enlace por referencia

add_action("some_action",array(&$this,"somefunction"))

en lugar de

add_action("some_action",array($this,"somefunction"))

Como se menciona en bainternet, también puede usar un patrón singleton para asegurarse de que un objeto específico se instancia solo una vez (las llamadas adicionales devuelven la referencia a ese objeto).

También podría considerar hacer que algunas funciones sean estáticas (dándoles la palabra clave estática. Esto generalmente se hace con funciones de tipo "auxiliar" que no interactúan con el resto de la clase. Se pueden llamar métodos estáticos sin instanciar una clase.

También puede pasar funciones estáticas a una acción / filtro:

add_action("some_action",array("ClassName","Method"))

También revisé http://codex.wordpress.org/Plugin_API/Action_Reference y descubrí que los complementos solo se pueden cargar en dos etapas en la solicitud (muplugins_loaded y plugins_loaded).

Arevico
fuente
3
Cuando un objeto se envía por argumento, se devuelve o se asigna a otra variable, las diferentes variables no son alias: contienen una copia del identificador, que apunta al mismo objeto. del manual de PHP . En una llamada o filtro de acción, la clase se envía como argumento. Desde PHP5 no hay necesidad de pasarlo como referencia.
Ralf912
Estoy corregido
Arevico