5

Im teaching myself namespaces and OOP in wordpress at the moment so bare with me.

In the base of my plugin I'm loading activation and deactivation hooks. Currently the deactivation hook works but the activation hook doesn't, it just fails silently (WP_DEBUG is on).

The base file declares a namespace and a constant, and then requires the class files for activation and deactivation and then registers the hooks. Activation and deactivation are functionally identical with each requiring and instantiating a error logging class, and sending a message to a method.

I've poured over the documentation for both register_deactivation_hook and for register_activation_hook (especially the contributor notes) and I've not been able to resolve this, so any thoughts on why one works and the other does not will be greatly appreciated.

The file structure is as follows:

/plugin/
    plugin.php   
/plugin/includes/
         ActivatorClass.php
         DeactivatorClass.php
         ErrorLogClass.php

/plugin/plugin.php

<?php
namespace company\pluginName;

/**
 * Plugin Name:       Plugin Name
 * Plugin URI:        http://url
 * Description:       A demo plugin 
 * Version:           0.0.1
 * Author:            me
 */


function pluginInit() {

    // Machine file path
    define( 'PLUGIN_PATH', realpath( plugin_dir_path( __FILE__ ) ) . DIRECTORY_SEPARATOR );

    /**
    * Runs during plugin activation.
    * Documented in includes/ActivatorClass.php
    */
    require_once PLUGIN_PATH . 'includes/ActivatorClass.php';
    register_activation_hook( __FILE__, array( __NAMESPACE__ . '\\ActivatorClass', 'activate' ) );

    /**
    * Runs during plugin deactivation.
    * Documented in includes/DeactivatorClass.php
    */
    require_once PLUGIN_PATH  . 'includes/DeactivatorClass.php';
    register_deactivation_hook( __FILE__, array( __NAMESPACE__ . '\\DeactivatorClass', 'deactivate' ) );
}

add_action( 'plugins_loaded', __NAMESPACE__ . '\\pluginInit' );

plugin/includes/ActivatorClass.php

 <?php
 namespace company\pluginName;

 /**
  * Fired during plugin activation
  *
  * This class defines all code necessary to run during the plugin's activation.
  *
  * @since      0.0.1
  * @package    plugin\pluginName\
  * @author     me
  */
  class ActivatorClass {

      /**
       * Fired during plugin activation
       *
       * @since    0.0.1
       */
      public static function activate() {
          require ( PLUGIN_PATH. '/includes/ErrorLogClass.php');
          $activate = new ErrorLog();
          $activate->log('Plugin Activated');
      }
  }

/plugin/includes/ErrorLogClass.php

<?php
namespace company\pluginName;

/**
* Class ErrorLog
*
* @since      0.0.1
* @package    plugin\pluginName\
* @author     me
*/

 class ErrorLog {

    /**
     * The error(s) to be logged
     * @var array | string
     */
    protected $log;

    /**
     * The logging method
     *
     * @param $log
     */
    public static function log( $log ) {
        if ( true === WP_DEBUG ) {
            if ( is_array( $log ) || is_object( $log ) ) {
                error_log( print_r( $log, true ) );
            } else {
                error_log( $log );
            }
        }
    }
 }
  • I think the problem here is that you place register_activation_hook() within the plugins_loaded hook. Try the global scope instead. – birgire May 8 '16 at 17:03
  • 1
    Found a relevant note in the Codex here: " Registering the hook inside the 'plugins_loaded' hook will not work. You can't call register_activation_hook() inside a function hooked to the 'plugins_loaded' or 'init' hooks (or any other hook). These hooks are called before the plugin is loaded or activated." – birgire May 8 '16 at 17:24
  • 1
    @birgire Yup moving register_activation_hook outside of the init function did the trick. More than a touch annoyed that I didn't catch that note earlier - many thanks. Now how about I just add a note developer.wordpress.org documentation! – orionrush May 8 '16 at 20:04
  • @orionrush, great, yes that might be a good idea ;-) – birgire May 8 '16 at 20:05
5

The reason that the plugin activation hook wasn't working in the code provided in the question is that on plugin activation the plugins_loaded hook is never run. Since the register_activation_hook hook was hooked from plugins_loaded it was never run on activation. And since it's never fired ever again, this way of hooking results in register_activation_hook never firing.

The solution is to register the activation hook from the main plugin file and not attached to any hooks. In fact, this is the only way that you can run the activation hook. After a plugin is activated there are only two other hooks run: that particular plugin activation hook and shutdown. It's possible to add hooks to shutdown and they will fire on plugin activation, but it fires after the plugin activation hook.

/**
 * Plugin Name: WordPress Namespace OOP Plugin Example
 */
declare( strict_types = 1 );
namespace StackExchange\WordPress;

//* Start bootstraping the plugin
require( __DIR__ . '/includes/plugin.php' );
$WordPressStackExchangePlugin = new plugin();
\add_action( 'plugins_loaded', [ $WordPressStackExchangePlugin, 'plugins_loaded' ] );

//* Register activation hook
\register_activation_hook( __FILE__, [ __NAMESPACE__ . '\\ActivatorClass', 'activate' ] );

The activation hook would then call the static method activate from the StackExchange\WordPress\ActivatorClass class.

Notes:

  1. Strict typing requires PHP > 7.0.
  2. Array shorthand requires PHP > 5.4
  3. Namespacing and __DIR__ require PHP > 5.3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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