0

I am trying to register an activation hook for my plugin. The plugin is using classes and the actual activation method is held in a separate admin class. Reading the documentation for register_activation_hook() it seems like the first parameter $file should always be the file of the main plugin file:

Path to the main plugin file inside the wp-content/plugins directory. A full path will work.

The two classes are kept in separate files, which looks something like this.

This is the main plugin file:

<?php 
/* my-plugin.php */

include_once(plugin_dir_path(__FILE__) . '/admin/my-plugin-admin.php');

register_activation_hook(__FILE__, array('MyPluginAdmin', 'activate'));

class MyPlugin {
}

While this is the admin part, which also contains the activation routine:

<?php
/* my-plugin-admin.php */

class MyPluginAdmin {
  public static function activate() {
    // This method is called in both cases,
    // but in the first example a php warning is generated
  }
}

My problem is that static activate method is actually triggered on activation, but I still get a php warning which looks like this:

PHP Warning:  call_user_func_array() expects parameter 1 to be a valid callback, class 'MyPluginAdmin' not found in /var/www/html/wp/wp-includes/class-wp-hook.php on line 287
PHP Stack trace:
1. {main}() /var/www/html/wp/wp-admin/plugins.php:0
2. activate_plugin($plugin = 'my-plugin/my-plugin.php', $redirect = 'http://localhost/wp/wp-admin/plugins.php?error=true&plugin=my-plugin%2Fmy-plugin.php', $network_wide = FALSE, $silent = *uninitialized*) /var/www/html/wp/wp-admin/plugins.php:43
3. do_action($tag = 'activate_my-plugin/my-plugin.php', $arg = FALSE) /var/www/html/wp/wp-admin/includes/plugin.php:586
4. WP_Hook->do_action($args = array (0 => FALSE)) /var/www/html/wp/wp-includes/plugin.php:453
5. WP_Hook->apply_filters($value = '', $args = array (0 => FALSE)) /var/www/html/wp/wp-includes/class-wp-hook.php:311
6. call_user_func_array:{/var/www/html/wp/wp-includes/class-wp-hook.php:287}(array (0 => 'MyPluginAdmin', 1 => 'activate'), array (0 => FALSE)) /var/www/html/wp/wp-includes/class-wp-hook.php:287

If I change the call to register_activation_hook() into:

register_activation_hook(plugin_dir_path(__FILE__) . '/admin/my-plugin-admin.php', array('MyPluginAdmin', 'activate'));

Then the warning message disappears. So, my question is what is the correct way to use register_activation_hook() and why does it work in both above cases although it throws a warning in the first scenario?

1

You first example looks corrent. There is however a typo, hence class 'MyPluginAdmin' not found.

You include myplugin-admin.php, but then your question seems to suggest the page holding the class is in fact my-plugin-admin.php (with a hypen).

If I correct the typo and run the code there are no warnings.

Edit (this works correctly):

my-plugin.php:

<?php 
/*
Plugin Name: my-plugin.php
*/

include_once(plugin_dir_path(__FILE__) . '/my-plugin-admin.php');

register_activation_hook(__FILE__, array('MyPluginAdmin', 'activate'));

class MyPlugin {
}

my-plugin-admin.php:

<?php
/* my-plugin-admin.php */

class MyPluginAdmin {
  public static function activate() {
  }
}

With my-plugin.php and my-plugin-admin.php both in the same directory. Does my-plugin-admin.php have the correct permissions?

  • That was just a typo, the path to the file is correct, so this seems not to be the problem. – Cyclonecode Sep 13 '18 at 7:36
  • @Cyclonecode your second version activates the plugin, but the activation function isn't run. The $file parameter is definitely incorrect, you end up with something like my-plugin.php/my-plugin-admin.php. Are both of the files in the same directory? – Matt Sep 13 '18 at 7:57
  • The MyPluginAdmin::activate method are run in both cases? The real plugin has its admin file located in a subfolder i.e admin/my-plugin-admin.php. Very strange that only the second version works without throwing a warning? – Cyclonecode Sep 13 '18 at 9:53
  • @Cyclonecode No, MyPluginAdmin::activate is not run in the second version. You can test this by just putting an echo in the activate function (activation hooks aren't allowed to output). The first example fails to activate with a The plugin generated x characters of unexpected output during activation. whereas the second activates as the function is not run. Are you including the directory in the include ie. include_once(plugin_dir_path(__FILE__) . 'admin/my-plugin-admin.php'); , because you haven't in your example code. – Matt Sep 13 '18 at 10:23
  • Yes of course I'm including the directory path in the second example. The path is absolutely correct, since it is the same path used for including the actual file. The above is just an example, shouldn't matter if it is in a sub folder as long as the path is correct. I updated the question to match the actual structure of my plugin files. – Cyclonecode Sep 13 '18 at 10:33

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.