I’ve started my first plugin and I need to store values returned from an API call to a database. But before I do that, I need to be able to make a database table. I have the following code in a file that is required of the main plugin file:
register_activation_hook(__FILE__, 'PLUGIN_activation');
function PLUGIN_activation() {
//setup DB Tables
global $wpdb;
$table_name = $wpdb->prefix . "table_name";//insert actual tablename here
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
event_id text NOT NULL,
event_date mediumint(8) DEFAULT '00000000' NOT NULL,
event_unique mediumint(13) NOT NULL,
name tinytext NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql );
}
I have reinstalled the plugin and activated it, but nothing happened.
For some reason, the table is not being created. What could be stopping this?
1 Answer
Note that the $file
in register_activation_hook( $file, $callback )
, should be equal to path to the main plugin file, but when you have it in a sub file as __FILE__
then it’s not the same! That means your callback is never called.
I would also recommend prefixing the function’s name to avoid possible name collision or use namespaces.
More in the Codex here.
Update
It’s informative to peek into the function’s definition:
/**
* Set the activation hook for a plugin.
*
* When a plugin is activated, the action 'activate_PLUGINNAME' hook is
* called. In the name of this hook, PLUGINNAME is replaced with the name
* of the plugin, including the optional subdirectory. For example, when the
* plugin is located in wp-content/plugins/sampleplugin/sample.php, then
* the name of this hook will become 'activate_sampleplugin/sample.php'.
*
* When the plugin consists of only one file and is (as by default) located at
* wp-content/plugins/sample.php the name of this hook will be
* 'activate_sample.php'.
*
* @since 2.0.0
*
* @param string $file The filename of the plugin including the path.
* @param callable $function The function hooked to the 'activate_PLUGIN' action.
*/
function register_activation_hook($file, $function) {
$file = plugin_basename($file);
add_action('activate_' . $file, $function);
}
and this is the corresponding do_action
call for the plugin acitvation in the activate_plugin()
function:
/**
* Fires as a specific plugin is being activated.
*
* This hook is the "activation" hook used internally by register_activation_hook().
* The dynamic portion of the hook name, `$plugin`, refers to the plugin basename.
*
* If a plugin is silently activated (such as during an update), this hook does not fire.
*
* @since 2.0.0
*
* @param bool $network_wide Whether to enable the plugin for all sites in the network
* or just the current site. Multisite only. Default is false.
*/
do_action( "activate_{$plugin}", $network_wide );
Example
Let’s walk through this with a real plugin.
So take for example the WooCommerce plugin, that has the main plugin file:
/full/path/to/wp-content/woocommerce/woocommerce.php
where it defines:
register_activation_hook( __FILE__, array( 'WC_Install', 'install' ) );
where $file
is __FILE__
or
/full/path/to/wp-content/woocommerce/woocommerce.php
Then the line:
$file = plugin_basename( $file );
becomes:
$file = plugin_basename( '/full/path/to/wp-content/woocommerce/woocommerce.php' );
that gives:
$file="woocommerce/woocommerce.php";
Then the dynamic hook:
add_action('activate_' . $file, $function);
generates:
add_action('activate_woocommerce/woocommerce.php', $function);
So if WooCommerce would place the registration activation hook in a special file under e.g.
/full/path/to/wp-content/woocommerce/include/activation.php
then this would be the value of __FILE__
and we would be registering the following action:
add_action('activate_woocommerce/include/activation.php', $function);
but there’s no do_action()
call for that one.
Instead they might store the main plugin file path, to use it elsewhere, like they already do in the main plugin file here:
$this->define( 'WC_PLUGIN_FILE', __FILE__ );
Hope it helps!