Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Is there some documentation somewhere that explains what is the life cycle of the plugins?

I'm starting a new plugin with OOP style, and I just found out that my main class is being instanciated a lot (thanks to Xdebug and Netbeans).
I wonder why, and it annoys me because I'm instanciating a Dropbox-API object, and I really didn't think WordPress would just instanciate my main class that much.

I haven't found anything related to the plugins life cycle in the Codex nor on Google.

share|improve this question
    
And here, have you searched here? :) –  brasofilo Jul 24 '12 at 14:42
15  
YouPorn can always define your class as a singleton stackoverflow.com/questions/203336/… –  Bainternet Jul 24 '12 at 15:10
    
thanks. I didn't thought about 'best practices'. I read a lot of things on the Codex, including Coding Guidelines but it's not here.. Will try the singleton then, but still, I find it strange that the plugin php is called multiple times.. No ? Bainternet be careful with your autocomplete :) –  RitonLaJoie Jul 24 '12 at 16:04
    
brasofilo, making a singleton would help but doesn't answer the question which is : why is the code ran multiple times inside my plugin ? The OO class in the URL you linked is doing exactly what I do –  RitonLaJoie Jul 24 '12 at 16:09
2  
Just had to +1 the question. Just for the comment and upvotes :D –  kaiser Nov 3 '12 at 1:15
show 1 more comment

2 Answers

I'm starting a new plugin with OOP style

What does 'OOP style' means for you? Wrapping all your functions with a class statement? Then you doing it wrong. You missuse the class as namespace.

and I just found out that my main class is being instanciated a lot

Huh?

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

Try it and count the number of files created. If i try it out, there is one file created for each page request. This means, only one instance of the Foo class for each page request.

Let's try a action call

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

If I look in my wp-content dir, I found two files. No more. One file is created when the class instance is created. And one is created when the action call is done.

OK, let's do some stupid things with our instance. Remove the add_action( 'plugins_loaded', .. ) and add this code instead:

function bar( $foo ) {

    $baz = $foo;
    return $baz;
}

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

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

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

How many files do you expect? I expect two. One from the constructor, one from the method.

A new instance is created only when the new operator is used.

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

Now I count four files. Two from the constructor and two from the method. This is because WordPress first include the plugin and then do the action hook plugins_loaded.

Best practice is to use the action hook plugins_loaded instead of creating an instance out of a function because, if the plugin file is included anywhere (e.g. in another file of your plugin), a new instance of the class is created everytime the file is included. The action hook plugins_loaded is done only once for every page request.

share|improve this answer
add comment

What might happen is that you pass a copy of you class to a filter or action. For example, if you want to directly modify class variables inside a hook or filter you should also pass the hook by reference

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

instead of

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

As is mentioned by bainternet you can also use a singleton pattern to make sure that a specific object is instanciated only once (further calls return the reference to that object).

You could also consider making some functions static (by giving them the static keyword. This is usually done to 'helper'-like functions which don't interact with the rest of the class. Static methods can be called without instanciating a class.

You can also pass static functions to an action/filter:

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

I also checked http://codex.wordpress.org/Plugin_API/Action_Reference and found that plugins can only be loaded at two stages in the request (muplugins_loaded and plugins_loaded).

share|improve this answer
2  
When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object. from the PHP manual. In an action call or filter, the class is send as argument. Since PHP5 there is no need to pass it as reference. –  Ralf912 Apr 25 '13 at 18:53
    
I stand corrected –  Setsuna Apr 25 '13 at 19:59
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.