I'm trying to force password change upon first user login, which overall is not working, but so far I find a problem update_user_meta() is not updating at all, this is my code:

function track_last_login($login)
    global $user_ID;
    $user = get_userdatabylogin($login);
    $Nlogins = (int)get_user_meta($user->ID, 'Nlogins', true);

    if (!$Nlogins) $Nlogins=1;
    else $Nlogins++;

    update_user_meta($user->ID, 'Nlogins', $Nlogins);

    if ($Nlogins==1)
        add_action('admin_notices', 'showAdminMessagePwd');
        header("Location: http://example.com/wp-admin/profile.php");
        remove_action('admin_notices', 'showAdminMessagePwd');


//(showAdminMessagePwd is a function already defined)

According to my log messages, the value of Nlogins is 1 before update_user_meta but it stays in 0 in database an every new login is like the first.

What am I doing wrong?

Another question is: Why does *add_action('admin_notices', 'showAdminMessagePwd')* only works when called from outside a function (directly in functions.php) and not when called inside this function.

Thank you

  • Looks like it didn't work when the meta_key has a 0 value in DB, but works when it doesn't exist or has a value>=1, so this part is solved. So, my other question was: Why does add_action('admin_notices', 'showAdminMessagePwd') only works when called from outside a function (directly in functions.php) and not when called inside this function?
    – user761076
    Jun 15, 2012 at 6:11
  • Edit the question with the new question
    – Bainternet
    Jun 15, 2012 at 6:37

2 Answers 2


In response to the extended question, i.e. Another question is[...]:

It is worth noting that Wordpress' plugin API does not persist between requests - that is to say, any functions associated with actions through Wordpress' add_action() are only associated for the duration of the script's execution. Each subsequent request served by Wordpress must once again bind functions with their proper actions (again, only for the duration of the request/script execution).

That in mind, you are binding the function showAdminMessagePwd() to the action admin_notices immediately before you execute a header-redirect, which should briefly prompt the client browser to terminate the request and start a new one at the indicated location. I may be misinterpreting the situation, but it seems reasonable that showAdminMessagePwd() is no longer bound to the action admin_notices when the script at http://example.com/wp-admin/profile.php executes as the add_action() call that binds it was executed in the context of an entirely separate request.

Binding the action within your functions.php file and outside of a function works fine because all of the code in a theme's functions file is executed whenever the theme gets loaded (for the intents and purpose of this question, virtually always). Binding the action in a function will work flawlessly so long as the function is executed, and your function bound before the admin_notices action is executed.

One solution might be to attach the logic that determines whether or not to display to an action that executes on every request rather than wp_login, which only executes after a user has authenticated themselves. Such an implementation might look something along the lines of

function track_last_login( $login ) {
    $user = get_user_by( 'login', $login );
    $nLogins = (int) get_user_meta( $user->ID, 'Nlogins', true );

    update_user_meta( $user->ID, 'Nlogins', $nLogins + 1 );

    if( $nLogins === 1 )
        header("Location: http://example.com/wp-admin/profile.php");
add_action( 'wp_login', 'track_last_login' );

function admin_password_notice() {
    //If the user isn't logged in, or they are viewing pages outside of the dashboard, ignore them.
    if( !is_user_logged_in() || !is_admin() )

    $user = wp_get_current_user();
    $nLogins = (int) get_user_meta( $user->ID, 'Nlogins', true );

    if( $nLogins === 1 )
        add_action('admin_notices', 'showAdminMessagePwd');
add_action( 'after_theme_setup', 'admin_password_notice' );

Note that no calls to remove_action( 'admin_notices', 'showAdminMessagePwd' ) are necessary as, if $nLogins does not equal 1, the function is never bound to the action (no calls to add_action( 'admin_notices', 'showAdminMessagePwd' ) have been made), and thus no binding exists to be removed.

Also note that the function get_userdatabylogin() has been deprecated as of Wordpress 3.3.


I'm not sure how is the flow going on exactly, but I had an issue with a very similar problem where I'm dumping the value above update_user_meta and it works below (even in the DB) and it doesn't work at all anywhere without the var_dump. I've reported it on Trac but no response so far.

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.