register_activation_hook()
云策文档标注
概述
register_activation_hook() 用于为插件设置激活钩子,当插件激活时触发 'activate_PLUGINNAME' 动作。该函数接受插件文件路径和回调函数作为参数,内部通过 add_action() 实现钩子注册。
关键要点
- 钩子名称基于插件文件路径生成,例如 'activate_sampleplugin/sample.php'。
- 参数 $file 必须是插件主文件的路径,$callback 是激活时要执行的函数。
- 激活钩子不能在 'plugins_loaded' 或 'init' 等钩子内注册,因为这些钩子在插件激活前已触发。
- 激活后页面会立即重定向,因此无法直接使用 add_action() 或 add_filter(),但可通过 add_option() 或 do_action() 间接处理。
- 全局变量在激活函数中可能无法访问,需在函数内外显式声明 global。
- 回调函数可接受一个布尔参数 $network_wide,用于判断插件是否在网络范围内激活。
- 对于单例类或命名空间,需使用数组或命名空间前缀指定回调。
- 激活钩子适用于执行一次性任务,如创建数据库表或刷新重写规则。
代码示例
register_activation_hook( __FILE__, 'my_plugin_activate' );
function my_plugin_activate( $network_wide ) {
if ( $network_wide ) {
// 网络激活处理
} else {
// 单站点激活处理
}
// 激活代码,如创建选项或数据库表
}注意事项
- 避免在 Multisite 中滥用激活钩子,某些情况下使用基于 admin_init 的升级例程更合适。
- 钩子名称中的斜杠和点可能被代码规范检查工具拒绝,需注意手动调用时的兼容性。
- 激活钩子应注册在插件主文件中,但回调函数可以定义在其他文件中。
原文内容
Set the activation hook for a plugin.
Description
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’.
Parameters
$filestringrequired-
The filename of the plugin including the path.
$callbackcallablerequired-
The function hooked to the
'activate_PLUGIN'action.
Source
function register_activation_hook( $file, $callback ) {
$file = plugin_basename( $file );
add_action( 'activate_' . $file, $callback );
}
Changelog
| Version | Description |
|---|---|
| 2.0.0 | Introduced. |
Skip to note 14 content
orionrush
Note that register_activation_hook must not be registered from within another hook for example ‘plugins_loaded’ or ‘init’ as these will have all been called before the plugin is loaded or activated.
This will NOT work:
function pluginInit() { require_once dirname(__FILE__) . '/includes/Activator.php'; register_activation_hook( __FILE__, 'Activator', 'activate' ) ); } add_action( 'plugins_loaded', 'pluginInit' );Skip to note 15 content
Codex
Singleton class pattern
If your plugin uses the singleton class pattern, add the activation hook like so:
class MyPlugin { static function install() { // do not generate any output here } } register_activation_hook( __FILE__, array( 'MyPlugin', 'install' ) );If the class that holds your activation function/method is in some additional file, register your activation function like this:
include_once dirname( __FILE__ ) . '/your_additional_file.php'; register_activation_hook( __FILE__, array( 'YourAdditionalClass', 'on_activate_function' ) );Or, because the activation hook requires a static function, if you’re inside of a __construct():
register_activation_hook( __FILE__, array( 'MyPlugin', 'YOUR_METHOD_NAME' ) );Skip to note 16 content
ics1010
There’s a comment here that could make this confusing by giving incorrect information. The code does NOT have to be in the main file, unless you’re doing something like a single file plugin. The thing to know is that the first argument is the name required to get your code to fire, not what file the code is in. Example:
<br />
Main plugin file: plugin/myplugin/myplugin.php<br />
include 'some_class.php';<br />
$obj = new other_class();</p>
<p>Other plugin file: plugin/myplugin/some_class.php<br />
class some_class {<br />
__constructor() {<br />
register_activation_hook(__DIR__.'/myplugin.php',array($this,'activate');<br />
}<br />
public function activate() { ... }<br />
}<br />
Skip to note 17 content
tjkwebdev
If calling this within a namespace:
register_activation_hook( __FILE__, __NAMESPACE__ . 'my_activate_callback' );Source: http://stackoverflow.com/questions/37863766/wordpress-not-recognizing-function-during-plugin-activation
Skip to note 18 content
mallorydxw-old
According to @nacin (a lead developer for WordPress), you shouldn’t use activation hooks (especially on multisite). You should do this instead:
“It’s far better to use an upgrade routine fired on admin_init, and handle that per-site, basing it on a stored option.”
Source: https://core.trac.wordpress.org/ticket/14170#comment:68
Skip to note 19 content
Koen Reus
The hooked function has one boolean argument,
$network_widewhich indicates if the plugin is network activated.register_activation_hook(__FILE__, 'my_plugin_activate'); function my_plugin_activate($network_wide){ if($network_wide){ //Plugin is network activated $site_ids = get_sites(array('fields' => 'ids')); foreach($site_ids as $site_id){ //Perform something on all sites within the network switch_to_blog($site_id); my_plugin_install_site(); restore_current_blog(); } return; } my_plugin_install_site(); } function my_plugin_install_site(){ //Do something }admin_initfires on every admin page load, but if you follow Nacin’s recommendation and condition the callback on a stored option, then the cost is near-zero.Skip to note 20 content
Mehdi Soltani
Sending arguments with callable function
Imagine that you have OOP structure for your plugin and need to observe SOLID principle inside it.
For this reason, you need to Dependency Injection with callable function inside your register_activation_hook function.
Sample code is like in the following:
Note: I used both way to show calling callable function with argument and without it in activation and deactivation hooks to bold using each of them. Usage of callable function with argument is in register_activation_hook.
https://github.com/msn60/oop-wordpress-plugin-boilerplate</a> * @since 1.0.0 * @package Plugin_Name_Name_Space * * @wordpress-plugin * Plugin Name: OOP WordPress Plugin Boilerplate * Plugin URI: <a href="https://github.com/msn60/oop-wordpress-pluging-boilerplate-light-version" rel="nofollow ugc">https://github.com/msn60/oop-wordpress-pluging-boilerplate-light-version</a> * Description: Description for OOP Plugin * Version: 1.0.2 * Author: Mehdi Soltani <soltani.n.mehdi@gmail.com> * Author URI: <a href="https://wpwebmaster.ir" rel="nofollow ugc">https://wpwebmaster.ir</a> * License: GPL-2.0+ * License URI: <a href="http://www.gnu.org/licenses/gpl-2.0.txt" rel="nofollow ugc">http://www.gnu.org/licenses/gpl-2.0.txt</a> */ /* * Define your namespaces here by use keyword * */ use Plugin_Name_Name_SpaceIncludesInit{ Constant, Activator }; use Plugin_Name_Name_SpaceIncludesConfigInitial_Value; use Plugin_Name_Name_SpaceIncludesUninstall{ Deactivator, Uninstall }; /** * If this file is called directly, then abort execution. */ if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Class Plugin_Name_Plugin * * This class is primary file of plugin which is used from * singletone design pattern. * * @package Plugin_Name_Name_Space * @author Your_Name <youremail@nomail.com> * @see Plugin_Name_Name_SpaceIncludesInitCore Class * @see Plugin_Name_Name_SpaceIncludesInitConstant Class * @see Plugin_Name_Name_SpaceIncludesInitActivator Class * @see Plugin_Name_Name_SpaceIncludesUninstallDeactivator Class * @see Plugin_Name_Name_SpaceIncludesUninstallUninstall Class */ final class Plugin_Name_Plugin { /** * Instance property of Plugin_Name_Plugin Class. * This is a property in your plugin primary class. You will use to create * one object from Plugin_Name_Plugin class in whole of program execution. * * @access private * @var Plugin_Name_Plugin $instance create only one instance from plugin primary class * @static */ private static $instance; /** * @var Initial_Value $initial_values An object to keep all of initial values for theme */ protected $initial_values; /** * Plugin_Name_Plugin constructor. * It defines related constant, include autoloader class, register activation hook, * deactivation hook and uninstall hook and call Core class to run dependencies for plugin * * @access private */ public function __construct() { /*Define Autoloader class for plugin*/ $autoloader_path = 'includes/class-autoloader.php'; /** * Include autoloader class to load all of classes inside this plugin */ require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . $autoloader_path; /*Define required constant for plugin*/ Constant::define_constant(); /** * Register activation hook. * Register activation hook for this plugin by invoking activate * in Plugin_Name_Plugin class. * * @param string $file path to the plugin file. * @param callback $function The function to be run when the plugin is activated. */ register_activation_hook( __FILE__, function () { $this->activate( new Activator( intval( get_option( 'last_your_plugin_name_dbs_version' ) ) ) ); } ); /** * Register deactivation hook. * Register deactivation hook for this plugin by invoking deactivate * in Plugin_Name_Plugin class. * * @param string $file path to the plugin file. * @param callback $function The function to be run when the plugin is deactivated. */ register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) ); } /** * Call activate method. * This function calls activate method from Activator class. * You can use from this method to run every thing you need when plugin is activated. * * @access public * @since 1.0.0 * @see Plugin_Name_Name_SpaceIncludesInitActivator Class */ public function activate( Activator $activator_object ) { global $wpdb; $activator_object->activate( true, new Table( $wpdb, PLUGIN_NAME_DB_VERSION, get_option( 'has_table_name' ) ) ); } /** * Create an instance from Plugin_Name_Plugin class. * * @access public * @since 1.0.0 * @return Plugin_Name_Plugin */ public static function instance() { if ( is_null( ( self::$instance ) ) ) { self::$instance = new self(); } return self::$instance; } /** * Load Core plugin class. * * @access public * @since 1.0.0 */ public function run_plugin_name_plugin() { // TODO: Do you codes here to run the plugin } /** * Call deactivate method. * This function calls deactivate method from Dectivator class. * You can use from this method to run every thing you need when plugin is deactivated. * * @access public * @since 1.0.0 */ public function deactivate() { Deactivator::deactivate(); } } $plugin_name_plugin_object = Plugin_Name_Plugin::instance(); $plugin_name_plugin_object->run_plugin_name_plugin();Skip to note 21 content
Rajan Karmaker
You can flush permalink if you have custom rewrite rules in your plugin
register_activation_hook( __FILE__, 'wpdocs_myplugin_activate' ); function wpdocs_myplugin_activate() { flush_rewrite_rules(); }Skip to note 22 content
Alvaro Torres
Really useful when, for example, when we need to create a DB table for our plugin functionalities:
<br />
function create_ourtable(){</p>
<p> global $wpdb;<br />
$prefix = $wpdb->prefix;<br />
$form_db = $prefix . "ourtable";</p>
<p> //Check if table exists. In case it's false we create it<br />
if($wpdb->get_var("SHOW TABLES LIKE '$form_db'") !== $form_db){</p>
<p> $sql = "CREATE TABLE $form_db(id mediumint unsigned not null primary key auto_increment, dates timestamp, names varchar(500), wp_user mediumint unsigned)";</p>
<p> require_once(ABSPATH . 'wp-admin/includes/upgrade.php');<br />
dbDelta($sql);<br />
}<br />
Skip to note 23 content
NateWr
If you’re looking for a similar hook that fires when a theme is activated, see after_switch_theme.
Skip to note 24 content
samwilson
Note that the WordPress code sniffer rules will reject the hook name that is constructed by this function, if you ever have to call the hook manually (for example, from a test). The
WordPress.NamingConventions.ValidHookName.UseUnderscoresrule rejects slashes and dots in hook names.Skip to note 25 content
Giulio Daprela
Please note that register_activation_hook() must be called from the main plugin file – the one that has “Plugin Name: …” directive.
This code added in the main plugin file will work:
require_once ( dirname( __FILE__ ) . '/includes/class-my-class.php' ); register_activation_hook( __FILE__, array ( $my_class, 'function_to_call') );However, if you try to add register_activation_hook() in the constructor of the class it won’t work because it’s not in the main plugin file.
Skip to note 26 content
Rinku Y
If you have a function called
myplugin_activate()in the main plugin file at eitherwp-content/plugins/myplugin.php or
wp-content/plugins/myplugin/myplugin.php
use this code:
register_activation_hook( __FILE__, 'myplugin_deactivate' );This will call the
myplugin_activate()function on activation of the plugin.