I found this action hook in wp-login.php file. It says it can be used to create custom actions to the wp-login. However, as I'm new to WP coding and PHP, I do not understand how {action} can work even though it is under double quotations? Here is the action hook:

do_action( "login_form_{$action}" );

In the plugin that I'm following, this action hook is added by this:

add_action( 'login_form_login', array( $this, 'redirect_to_custom_login' ));

How does login_form_login matches and replaces login_form_{action} ?

  • Please adjust the question's title, to make it more readable, thanks. Are you asking how "dynamic" actions compares to "static" actions? Or how actions works in general?
    – birgire
    Apr 18, 2017 at 18:30

2 Answers 2


This is a dynamic hook:

do_action( "login_form_{$action}" );

Meaning that it depends on the $action variable.

There are other such hooks used in the WordPress core.

You can check out the naming convention for dynamic hooks in the Core Contributor Handbook here. It's says e.g.:

Dynamic hooks should be named using interpolation rather than concatenation for readability and discoverability purposes.

Double quoted strings in PHP can parse variables, that's why it's not written with single quotes:

do_action( 'login_form_{$action}' );

Check out the curly syntax in the PHP docs in the variable parsing section.


If we have:

$action = 'login';

then it will generate the following action:

do_action( "login_form_login" );

that plugins can hook into via:

add_action( 'login_form_login', ... );

$action is a variable that is set on line 384 of wp-login.php (as of WordPress 4.7.3).

$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'login';

When WordPress gets to line 428, it evaluates the string inside the double quotations first as login_form_login if the $_REQUEST['action'] variable is not set. If that variable is set, for instance as register, then the string inside the double quotations would be evaluated as login_form_register.

When the the WordPress function do_action() is interpreted, see line 421 of wp-includes/plugin.php, does some stuff, and on line 453 applies the do_action() method of the $wp_filter global.

To see what this method does, we need to go to line 321 of wp-includes/class-wp-hook.php, which because hooks are just simplified filters, calls the apply_filters() method, which is on line 276 of the same file.

The relevant parts of this method are lines 296, 298, and 300 and they look like:

$value = call_user_func_array( $the_['function'], array() );

call_user_func_array() is a PHP function that calls a callback with an array of parameters.

WordPress stores the callbacks for each hook in the $wp_filter global. We add them using the add_action() and add_filter() functions.

add_action( 'login_form_login', array( $this, 'redirect_to_custom_login' ));

This is telling WordPress to add an action to the login_form_login hook and the callable callback is the redirect_to_custom_login method from $this object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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