Changing the username character limit from four to less characters

I want to create a user account on my multi-site installation of WordPress with a username less than 4 characters. But since WordPress has a limit of usernames at least being 4 characters, this error message is shown:

Username must be at least 4 characters.

Read More

I found a solution involving a mu-plugins folder in the wp-content folder, but it doesn’t work.
Is there any possible way that would allow me to create a user account with a username less than 4 characters?

Related posts

Leave a Reply

2 comments

  1. You can filter 'wpmu_validate_user_signup' and check if the error code matches the 4 character warning. Then just unset the error code.

    Sample plugin:

    <?php # -*- coding: utf-8 -*-
    /* Plugin Name: Allow short user names for multi site. */
    
    add_filter( 'wpmu_validate_user_signup', 'wpse_59760_short_user_names' );
    
    /**
     * Allow very short user names.
     *
     * @wp-hook wpmu_validate_user_signup
     * @param   array $result
     * @return  array
     */
    function wpse_59760_short_user_names( $result )
    {
        $error_name = $result[ 'errors' ]->get_error_message( 'user_name' );
        if ( empty ( $error_name )
            or $error_name !== __( 'Username must be at least 4 characters.' )
        )
        {
            return $result;
        }
    
        unset ( $result[ 'errors' ]->errors[ 'user_name' ] );
        return $result;
    }
    
  2. As there can be more than one error for user names, the accepted answer could remove errors we would want to preserve. For example entering a user name of 123 would now pass whereas it should presumably still give the error message 'Sorry, usernames must have letters too!'

    Modified sample code to fix this:

    /* Plugin Name: Allow short user names for multi site. */
    
    add_filter( 'wpmu_validate_user_signup', 'wpse_59760_short_user_names' );
    
    /**
     * Allow very short user names.
     *
     * @wp-hook wpmu_validate_user_signup
     * @param   array $result
     * @return  array
     */
    function wpse_59760_short_user_names( $result )
    {
        $error_name = $result[ 'errors' ]->get_error_messages( 'user_name' );
        if ( empty ( $error_name ) 
            or false===$key=array_search( __( 'Username must be at least 4 characters.' ), $error_name)
        )
        {
            return $result;
        }
    
    //  only remove the error we are disabling, leaving all others
        unset ( $result[ 'errors' ]->errors[ 'user_name' ][$key] );
    /**
     *  re-sequence errors in case a non sequential array matters
     *  e.g. if a core change put this message in element 0 then get_error_message() would not behave as expected)
     */
        $result[ 'errors' ]->errors[ 'user_name' ] = array_values( $result[ 'errors' ]->errors[ 'user_name' ] );
        return $result;
    }
    

    EDIT:
    This works in WordPress up to version 3.9.6 and again in 4.2

    Note that this does not work in WordPress 4.0 or 4.1 because https://core.trac.wordpress.org/ticket/22234 made the errors a private variable. Although a magic __get method was provided “for backwards compatability”, for arrays it returns a copy of an array (not a reference to the original) which is then not editable. If you have WP_DEBUG turned on you will get a PHP Notice saying “Notice: Indirect modification of overloaded property WP_Error::$errors has no effect in /path/to/plugin on line xxx”, otherwise the code fails silently and has no effect.

    It works again in version 4.2 because https://core.trac.wordpress.org/ticket/30891 reverted the change for WP_Error and a number of other places in core, though not so that code like this would work.

    For WordPress >=4.1 which gave us a remove method this also works:

    function wpse_59760_short_user_names( $result )
    {
        $error_name = $result[ 'errors' ]->get_error_messages( 'user_name' );
        if ( empty ( $error_name ) 
            or false===$key=array_search( __( 'Username must be at least 4 characters.' ), $error_name)
        )
        {
            return $result;
        }
    
        // remember any error data
        $data = $result[ 'errors' ]->get_error_data( 'user_name' );
    
        // remove all user name errors
        $result[ 'errors' ]->remove( 'user_name' );
    
        // add back in any other user name errors we want to keep
        foreach ( $error_name as $index=>$message ) {
            if ( $index !== $key ) 
                $result[ 'errors' ]->add( 'user_name', $message );
        }
    
        // restore any user_name error data that was present
        if ( !empty( $data ) ) 
            $result[ 'errors' ]->add_data( $data, 'user_name' );
    
        return $result;
    }