函数文档

do_action()

💡 云策文档标注

概述

do_action() 是 WordPress 中用于触发动作钩子的核心函数,它调用所有已通过 add_action() 附加到指定钩子的回调函数。开发者可以通过调用此函数来创建新的动作钩子,并传递额外参数给回调函数,类似于 apply_filters() 的工作方式。

关键要点

  • do_action() 用于执行指定动作钩子 $hook_name 的所有已注册回调函数。
  • 通过调用 do_action() 并指定新的钩子名称,可以动态创建自定义动作钩子。
  • 支持传递可变数量的额外参数(...$arg)给回调函数,参数类型和数量需与 add_action() 中定义的一致。
  • 函数内部处理了全局变量如 $wp_filter、$wp_actions 和 $wp_current_filter,并优先执行 'all' 钩子。
  • 注意:如果传递的 $arg 是仅包含一个对象的数组,出于向后兼容性,会将该对象直接传递给回调函数,而不是数组。

代码示例

// 定义回调函数,接受两个参数
function example_callback( $arg1, $arg2 ) {
    // 处理参数
}
add_action( 'example_action', 'example_callback', 10, 2 );

// 触发动作钩子,传递参数
$arg1 = 'value1';
$arg2 = 'value2';
do_action( 'example_action', $arg1, $arg2 );

注意事项

  • 确保 do_action() 传递的参数数量与 add_action() 中 $accepted_args 参数匹配,否则可能导致回调函数接收错误参数。
  • 在创建自定义钩子时,建议使用唯一且描述性的钩子名称,以避免与核心或其他插件冲突。
  • 注意 PHP 4 向后兼容性处理:当 $arg 是仅包含一个对象的数组时,回调函数会直接接收该对象,而不是数组。

📄 原文内容

Calls the callback functions that have been added to an action hook.

Description

This function invokes all functions attached to action hook $hook_name.
It is possible to create new action hooks by simply calling this function, specifying the name of the new hook using the $hook_name parameter.

You can pass extra arguments to the hooks, much like you can with apply_filters().

Example usage:

// The action callback function.
function example_callback( $arg1, $arg2 ) {
    // (maybe) do something with the args.
}
add_action( 'example_action', 'example_callback', 10, 2 );

/*
 * Trigger the actions by calling the 'example_callback()' function
 * that's hooked onto `example_action` above.
 *
 * - 'example_action' is the action hook.
 * - $arg1 and $arg2 are the additional arguments passed to the callback.
do_action( 'example_action', $arg1, $arg2 );

Parameters

$hook_namestringrequired
The name of the action to be executed.
$argmixedoptional
Additional arguments which are passed on to the functions hooked to the action. Default empty.

Source

function do_action( $hook_name, ...$arg ) {
	global $wp_filter, $wp_actions, $wp_current_filter;

	if ( ! isset( $wp_actions[ $hook_name ] ) ) {
		$wp_actions[ $hook_name ] = 1;
	} else {
		++$wp_actions[ $hook_name ];
	}

	// Do 'all' actions first.
	if ( isset( $wp_filter['all'] ) ) {
		$wp_current_filter[] = $hook_name;
		$all_args            = func_get_args(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
		_wp_call_all_hook( $all_args );
	}

	if ( ! isset( $wp_filter[ $hook_name ] ) ) {
		if ( isset( $wp_filter['all'] ) ) {
			array_pop( $wp_current_filter );
		}

		return;
	}

	if ( ! isset( $wp_filter['all'] ) ) {
		$wp_current_filter[] = $hook_name;
	}

	if ( empty( $arg ) ) {
		$arg[] = '';
	} elseif ( is_array( $arg[0] ) && 1 === count( $arg[0] ) && isset( $arg[0][0] ) && is_object( $arg[0][0] ) ) {
		// Backward compatibility for PHP4-style passing of `array( &$this )` as action `$arg`.
		$arg[0] = $arg[0][0];
	}

	$wp_filter[ $hook_name ]->do_action( $arg );

	array_pop( $wp_current_filter );
}

Changelog

Version Description
5.3.0 Formalized the existing and already documented ...$arg parameter by adding it to the function signature.
1.2.0 Introduced.

User Contributed Notes

  1. Skip to note 4 content

    Example

    # ======= Somewhere in a (mu-)plugin, theme or the core ======= #
    
    /**
     * You can have as many arguments as you want,
     * but your callback function and the add_action call need to agree in number of arguments.
     * Note: `add_action` above has 2 and 'i_am_hook' accepts 2. 
     * You will find action hooks like these in a lot of themes & plugins and in many place @core
     * @see: <a href="https://codex.wordpress.org/Plugin_API/Action_Reference" rel="nofollow ugc">https://codex.wordpress.org/Plugin_API/Action_Reference</a>
     */
    
    # ======= e.g., inside your functions.php file ======= #
    
    /**
     * Define callback function
     * Inside this function you can do whatever you can imagine
     * with the variables that are loaded in the do_action() call above.
     */
    function wpdocs_who_is_hook( $a, $b ) {
    	echo '<code>';
    		print_r( $a ); // `print_r` the array data inside the 1st argument
    	echo '</code>';
    
    	echo '<br />'.$b; // echo linebreak and value of 2nd argument
    }
    
    // then add it to the action hook, matching the defined number (2) of arguments in do_action
    // see [https://codex.wordpress.org/Function_Reference/add_action] in the Codex 
    
    // add_action( $tag, $function_to_add, $priority, $accepted_args );
    add_action( 'wpdocs_i_am_hook', 'wpdocs_who_is_hook', 10, 2 );
    
    // Define the arguments for the action hook
    $a = array(
    	'eye patch'  => 'yes',
    	'parrot'     => true,
    	'wooden leg' => 1
    );
    $b = __( 'And Hook said: "I ate ice cream with Peter Pan."', 'textdomain' ); 
    
    // Executes the action hook named 'i_am_hook'
    do_action( 'wpdocs_i_am_hook', $a, $b );

    Result:

    Array ( 
    	['eye patch'] => 'yes'
    	['parrot'] => true
    	['wooden leg'] => 1
    )
    And hook said: "I ate ice cream with Peter Pan."

  2. Skip to note 5 content

    BIG GOTCHA:

    When calling do_action, if the $arg you pass in is an array with a single object, it will instead pass that obejct in and NOT an array. It doesn’t do the same switcheroo, however, if the array’s single item is anything other than an array

    E.g.,

    function my_callback( $should_be_an_array ){
       var_dump($should_be_an_array);
    }
    add_action( 'my_action', 'my_callback' );
    do_action( 'my_action', array(new stdclass()) );
    do_action( 'my_action', array( 'array_item_thats_not_an_object') );

    echoes out

    object(stdClass)[420]
    array (size=1)
      0 => string 'array_item_thats_not_an_object' (length=30)

    notice that the first time we passed in an array with an stdclass in it, but the callback function only received the stdclass, NOT an array

  3. Skip to note 6 content