¿Cómo cambiar programáticamente el nombre de usuario (user_login)?

19 jun 2013, 17:59:25
Vistas: 31.4K
Votos: 19

Como se indica en el título, ¿cómo cambiar programáticamente el nombre de usuario?

Quería usar la función wp_insert_user, pero parece que al actualizar el usuario actual, no cambia su nombre de usuario. ¿Debería usar $wpdb->update para eso? Si es así, ¿cómo se vería el código para cambiar el nombre de usuario? ¿Qué consecuencias tendría cambiar el nombre de usuario, dado que la API de WordPress no permite cambiar nombres de usuario?

1
Comentarios

Sé que esto fue hace 10 años que preguntaste, espero que mi respuesta aún pueda ayudarte :)

User User
14 abr 2023 08:14:50
Todas las respuestas a la pregunta 4
9
31

Estaba seguro de que wp_update_user() debería hacer esto.

Incluso recibe user_login como parámetro, pero parece que lo ignora cuando lo estableces.

Así que este código parece correcto, pero no funciona como desearías :( :

wp_update_user(
    ['ID' => $user_id, 'user_login' => $new_login] 
);

Tienes que ejecutar una consulta SQL personalizada para actualizar user_login:

global $wpdb;
$wpdb->update(
    $wpdb->users, 
    ['user_login' => $new_user_login], 
    ['ID' => $user_id]
);

Funciona correctamente y no creo que tenga consecuencias graves, porque WordPress usa los ID de usuario para asignar publicaciones/comentarios (y demás) al usuario.

El único problema que se me ocurre es que si este usuario está actualmente conectado, se cerrará su sesión después de cambiar el user_login.

19 jun 2013 18:10:12
Comentarios

En realidad no, revisa las notas de esta función (así como el código): Ten en cuenta que no podemos cambiar los nombres de usuario a través de esta función, de hecho los nombres de usuario no se pueden cambiar desde el panel de administración ya que WordPress no permite que se actualicen los nombres de usuario.

Mateusz Hajdziony Mateusz Hajdziony
19 jun 2013 18:13:59

¡Gracias, funciona genial! No hay problema con los usuarios conectados, ya que solo permito el cambio de nombre de usuario para usuarios desconectados (activación de cuenta por correo electrónico).

Mateusz Hajdziony Mateusz Hajdziony
19 jun 2013 18:40:39

@pogoking Algo que podrías considerar es que los enlaces permanentes de usuario o autor podrían romperse después de permitir que los usuarios cambien sus nombres de usuario si los enlaces permanentes "bonitos" están habilitados, por lo que podrías necesitar tomar medidas para compensar eso.

Ahmad M Ahmad M
19 jun 2013 19:19:39

@AhmadM Gracias Ahmad, pero como mencioné antes - los usuarios antes de la activación de su cuenta no aparecerán listados en ningún lugar, así que los enlaces permanentes no son un problema. ¡Gracias por la advertencia de todos modos!

Mateusz Hajdziony Mateusz Hajdziony
19 jun 2013 19:41:17

necesité agregar global $wpdb; para que funcione

Mau Mau
13 may 2015 05:52:50

@Mauro Bueno, si ejecutas este código dentro de una función, entonces sí - por supuesto. También tienes que declarar $user_id y $new_login, pero es obvio y no está relacionado con WP, ¿verdad?

Krzysiek Dróżdż Krzysiek Dróżdż
13 may 2015 19:53:26

Publicación antigua, pero estoy pensando en hacer esto mismo, valdría la pena verificar que no haya otro usuario con el mismo user_login registrado en tu sitio, ya que el formulario de inicio de sesión obviamente usa este valor para encontrar cuentas y coincidir con los hashes de contraseñas.

haxxxton haxxxton
24 may 2016 08:09:52

@haxxxton Tuve el mismo pensamiento, ! username_exists( sanitize_user( $new_user_login ) ); hará exactamente eso.

amarinediary amarinediary
27 mar 2021 16:00:55

Sugeriría agregar ya sea update_user_caches(get_user_by('id', $user_id)) o clean_user_cache($user_id) después de esa actualización si estás usando wp_object_cache. He descubierto por las malas que modificar directamente los registros de usuario en WP puede llevar a comportamientos muy inesperados de otra manera.

Dan B Dan B
13 may 2024 16:02:13
Mostrar los 4 comentarios restantes
1

También podrías considerar cambiar el user_nicename mediante la consulta SQL. Una vez hecho esto, todos los enlaces permanentes y otras funciones funcionarán perfectamente.

11 jun 2014 09:45:53
Comentarios

En su lugar, podrías considerar usar un slug de perfil basado en ID en lugar de uno basado en nice_name. Esto asegurará que el perfil tenga una URL universal y no tendrás páginas 404 aleatorias apareciendo (supongo que eso es mejor para SEO).

amarinediary amarinediary
27 mar 2021 16:06:35
0

Además de la respuesta de Krzysiek Dróżdż.

Si no deseas cerrar la sesión de los usuarios después de cambiar user_login, necesitas hacer lo siguiente para mantener al usuario conectado con los nuevos datos:

clean_user_cache($user->ID); // Limpiar caché del usuario
wp_clear_auth_cookie(); // Eliminar cookie de autenticación actual
wp_set_current_user($user->ID); // Establecer usuario actual
wp_set_auth_cookie($user->ID, true); // Crear nueva cookie de autenticación
update_user_caches($user); // Actualizar cachés del usuario
2 may 2024 23:06:56
0

Debes usar el filtro para modificar el $data cuando se actualice el usuario, no puedes actuar con el action al que normalmente te engancharías en una actualización de usuario.

También debes implementar varias de las medidas de seguridad y validación que WordPress aplica en su código dentro de tu nueva función.

Lo que puedes hacer:

  1. Engancharte al filtro wp_pre_insert_user_data. Asegúrate de hacerlo solo con los permisos correctos: add_filter( 'wp_pre_insert_user_data', 'prefix_change_user_login', 10, 4 );
  2. Ahora crea una función prefix_change_user_login donde obtengas el $data, el user_login del $_POST y lo pases por una serie de validaciones y saneamientos (ver https://github.com/WordPress/wordpress-develop/blob/bb27ffce6c3b10738008f9a054782945a0744960/src/wp-includes/user.php#L2076-L2498 para más detalles)
  3. Además, por supuesto, tendrás que permitir la edición real del campo de inicio de sesión del usuario en la pantalla de Editar Usuario del Administrador de WP, o pasar ese valor de alguna otra manera a tu código.

Un ejemplo de dicha función:

    /**
     * Actualiza el nombre de inicio de sesión del usuario
     *
     * @since x.x.x
     * @param array    $data {
     *     Valores y claves para el usuario.
     *
     *     @type string $user_login      El inicio de sesión del usuario. Solo incluido si $update == false
     *     @type string $user_pass       La contraseña del usuario.
     *     @type string $user_email      El email del usuario.
     *     @type string $user_url        La URL del usuario.
     *     @type string $user_nicename   El nombre "bonito" del usuario. Por defecto una versión segura para URL del inicio de sesión
     *     @type string $display_name    El nombre para mostrar del usuario.
     *     @type string $user_registered Timestamp MySQL que describe el momento en que el usuario se registró. Por defecto
     *                                   el timestamp UTC actual.
     * }
     * @param bool     $update   Si el usuario se está actualizando en lugar de crearse.
     * @param int|null $user_id  ID del usuario a actualizar, o NULL si el usuario se está creando.
     * @param array    $userdata El array crudo de datos pasado a wp_insert_user().
     */
    function prefix_change_user_login( $data, $update, $user_id, $userdata ){

        // ¡¡¡NO OLVIDES AÑADIR AQUÍ LA VALIDACIÓN CORRECTA DE NONCE Y REFERER!!!!

        $sanitized_user_login = sanitize_user( wp_unslash( $_POST['user_login'] ), true );// En nuestro caso obtenemos el nuevo inicio de sesión del valor POST del formulario en el Admin de WP. ¡Si esto es diferente en tu caso, adáptalo!

        /**
         * Filtra un nombre de usuario después de ser saneado.
         *
         * Este filtro se llama antes de que el usuario sea creado o actualizado.
         *
         * @since 2.0.3
         *
         * @param string $sanitized_user_login Nombre de usuario después de ser saneado.
         */
        $pre_user_login = apply_filters( 'pre_user_login', $sanitized_user_login );
        $illegal_logins = (array) apply_filters( 'illegal_user_logins', array() );

        // Elimina cualquier carácter no imprimible del string de inicio de sesión para ver si terminamos con un nombre vacío.
        $user_login = trim( $pre_user_login );

        if ( empty( $user_login )
            || mb_strlen( $user_login ) > 60
            || username_exists( $user_login )
            || in_array( strtolower( $user_login ), array_map( 'strtolower', $illegal_logins ), true )
        ) {
            return $data;
        }

        $data['user_login'] = $user_login;
        $user_nicename = sanitize_title( mb_substr( $user_login, 0, 50 ) );// ¿Quién sabe qué habían fumado los desarrolladores de WP cuando decidieron hacer el nicename 10 caracteres más corto que el nombre de inicio de sesión?
        global $wpdb;
        $user_nicename_check = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1", $user_nicename, $user_login ) );

        if ( $user_nicename_check ) {
            $suffix = 2;
            while ( $user_nicename_check ) {
                // user_nicename permite 50 chars. Resta uno por el guión, más la longitud del sufijo.
                $base_length         = 49 - mb_strlen( $suffix );
                $alt_user_nicename   = mb_substr( $user_nicename, 0, $base_length ) . "-$suffix";
                $user_nicename_check = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->users WHERE user_nicename = %s AND user_login != %s LIMIT 1", $alt_user_nicename, $user_login ) );
                $suffix++;
            }
            $user_nicename = $alt_user_nicename;
        }
        $data['user_nicename'] = $user_nicename;

        return $data;

    }

Esto te permitirá actualizar el nombre de inicio de sesión del usuario, y también actualizará el "nicename" del usuario (usado en archivos por ejemplo).

Por supuesto, esto aún requiere que "habilites" la edición en el área de Administración de WP, pero eso no debería ser muy difícil.

Nota que si ocurre algún error en el código anterior (el nombre de usuario ya existe, etc.) NO se muestra ningún error, en su lugar, el usuario simplemente se actualiza y vuelve al estado anterior.

Nota que, aunque este código está probado, depende de ti lo que hagas con él, y hay RAZONES por las que wp no permite actualizar el inicio de sesión del usuario.

14 abr 2023 08:14:18