0

I've added the code found here and slightly modified it so that the "Last Logged In" column is sortable but it doesn't sort the column correctly when I click it, can anyone see anything wrong with the code?

Thanks

// add two columns to the user list page
add_filter( 'manage_users_columns', 'my_manage_users_columns' );
function my_manage_users_columns( $columns ) {
    $columns['registration_date'] = 'Registered';
    $columns['last_login_date'] = 'Last Logged In';
    return $columns;
}

// provide data for the two added columns
add_filter( 'manage_users_custom_column', 'my_manage_users_custom_column', 10, 3 );
function my_manage_users_custom_column( $row_output, $column_id_attr, $user ) {
    $date_format = 'Y/m/d \a\t g:i a';
    $d1 = 0;
    switch ( $column_id_attr ) {
        case 'registration_date':
            $d1 = strtotime(get_userdata($user)->user_registered);
            break;
        case 'last_login_date':
            $session_tokens = get_user_meta( $user, 'session_tokens', true );
            if (!empty($session_tokens)) {
                $d1 = max(array_column(array_values($session_tokens),'login'));
            }
            break;
        default:
    }
    if ($d1 > 0) {
        $d2 = new DateTime("@$d1");
        return $d2->setTimezone(wp_timezone())->format($date_format);
    }
    return $row_output;
}

// make the registration date column sortable
add_filter( 'manage_users_sortable_columns', 'my_manage_users_sortable_columns' );
function my_manage_users_sortable_columns( $columns ) {
    return wp_parse_args( array( 'registration_date' => 'registered', 'last_login_date' => 'Last Logged In' ), $columns );
}

add_action( 'pre_user_query', 'misha_users_by_date_registered_by_default' );
function misha_users_by_date_registered_by_default( $query ) {
    global $pagenow;

    if ( is_admin() && 'users.php' == $pagenow ) {
        $query->query_orderby = 'ORDER BY user_registered DESC';
    }
    
    return $query;
}
3
  • the answer you used is incorrect and rests on a fatal misunderstanding of what the session_data field is for, the column it tries to add doesn't do what they thought it does. Even if you fix sorting that data, it is not reliable because WP deletes it when users log out or it expires, it's only used for storing active sessions. Anybody who clicks the logout link will have an untraceable login
    – Tom J Nowell
    Commented Feb 26, 2023 at 15:28
  • Following from what Tom said, you would have to store the last login every time someone logs in using update_user_meta, and order by that instead.
    – popnoodles
    Commented Feb 26, 2023 at 15:51
  • @popnoodles, where would I add that? Commented Feb 26, 2023 at 18:08

1 Answer 1

1

The default Last Login column only applies to users who are currently logged in. The timestamp is deleted when the user logs out.

First, you need to save the timestamp when a user logs in. This will save it to user_meta.


function save_login_timestamp( $user_login, $user ) {
    update_user_meta( $user->ID, 'last_login', time() );
}
add_action( 'wp_login', 'save_login_timestamp', 10, 2 );

To sort by this value you need to add a column to the users table and make it sortable.


// Add a new column to the users table
function add_last_login_column( $columns ) {
    $columns['wfls_last_login'] = 'Logged In'; // give this one a more accurate title
    $columns['last_login'] = 'Last Logged In'; // add a new one
    return $columns;
}
add_filter( 'manage_users_columns', 'add_last_login_column' );

// Display the last_login time for each user in the new column
function display_last_login_column( $value, $column_name, $user_id ) {
    if ( $column_name === 'last_login' ) {
        $last_login = get_user_meta( $user_id, 'last_login', true );
        if ( $last_login ) {
            return date( 'Y/m/d H:i', $last_login );
        }
        return 'Never';
    }
    return $value;
}
add_filter( 'manage_users_custom_column', 'display_last_login_column', 10, 3 );

// Make the column sortable
function make_last_login_column_sortable( $columns ) {
    $columns['last_login'] = 'last_login';
    return $columns;
}
add_filter( 'manage_users_sortable_columns', 'make_last_login_column_sortable' );

// Sort the users by last_login 
function sort_by_last_login( $query ) {
    if ( $query->get( 'orderby' ) === 'last_login' ) {
        $query->set( 'meta_key', 'last_login' );
        $query->set( 'orderby', 'meta_value_num' );
    }
}
add_action( 'pre_get_users', 'sort_by_last_login' );

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.