Как программно изменить имя пользователя (user_login)?

19 июн. 2013 г., 17:59:25
Просмотры: 31.4K
Голосов: 19

Как указано в заголовке, как программно изменить логин пользователя?

Я хотел использовать функцию wp_insert_user, но оказалось, что при обновлении текущего пользователя она не меняет его имя пользователя. Следует ли использовать $wpdb->update для этого? Если да, как будет выглядеть код для изменения имени пользователя? Какие последствия будет иметь изменение логина пользователя, учитывая, что API WordPress не позволяет менять имена пользователей?

1
Комментарии

Я знаю, что с момента вашего вопроса прошло уже 10 лет, но надеюсь, что мой ответ все еще может вам помочь :)

User User
14 апр. 2023 г. 08:14:50
Все ответы на вопрос 4
9
31

Я был уверен, что функция wp_update_user() должна это делать.

Она даже принимает user_login как параметр, но похоже, что игнорирует его, когда вы его устанавливаете.

Так что этот код выглядит нормально, но он не работает так, как хотелось бы :( :

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

Вам нужно выполнить пользовательский SQL-запрос для обновления user_login:

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

Это работает нормально, и я не думаю, что это имеет какие-то серьезные последствия, потому что WordPress использует ID пользователей для привязки записей/комментариев (и так далее) к пользователю.

Единственная проблема, о которой я могу подумать, это то, что если этот пользователь в данный момент авторизован, он будет разлогинен после изменения user_login.

19 июн. 2013 г. 18:10:12
Комментарии

На самом деле нет, ознакомьтесь с примечаниями к этой функции (а также с кодом): Обратите внимание, что мы не можем изменять имена пользователей через эту функцию, более того, имена пользователей нельзя изменить и из админ-панели, поскольку WordPress не позволяет обновлять имена пользователей.

Mateusz Hajdziony Mateusz Hajdziony
19 июн. 2013 г. 18:13:59

Спасибо, это отлично работает! Хотя беспокоиться о вошедших пользователях не стоит, так как я разрешаю смену имени пользователя только для вышедших из системы (активация аккаунта по электронной почте).

Mateusz Hajdziony Mateusz Hajdziony
19 июн. 2013 г. 18:40:39

@pogoking Возможно, вам стоит учесть, что постоянные ссылки пользователей или авторов могут перестать работать после разрешения смены имен пользователей, если включены ЧПУ, поэтому вам может потребоваться принять меры для компенсации этого.

Ahmad M Ahmad M
19 июн. 2013 г. 19:19:39

@AhmadM Спасибо, Ахмад, но как я уже говорил ранее - пользователи до активации аккаунта не будут отображаться нигде, так что проблема с постоянными ссылками отсутствует. Но спасибо за предупреждение!

Mateusz Hajdziony Mateusz Hajdziony
19 июн. 2013 г. 19:41:17

мне пришлось добавить global $wpdb;, чтобы это заработало

Mau Mau
13 мая 2015 г. 05:52:50

@Mauro Ну, если ты запускаешь этот код внутри функции, тогда да - конечно. Тебе также нужно объявить $user_id и $new_login, но это очевидно и не связано с WP, верно?

Krzysiek Dróżdż Krzysiek Dróżdż
13 мая 2015 г. 19:53:26

Старый пост, но я сам рассматриваю эту возможность. Стоит проверить, нет ли другого пользователя с таким же user_login на вашем сайте, так как форма входа использует это значение для поиска аккаунтов и проверки хэшей паролей.

haxxxton haxxxton
24 мая 2016 г. 08:09:52

@haxxxton У меня была та же мысль, ! username_exists( sanitize_user( $new_user_login ) ); сделает именно это.

amarinediary amarinediary
27 мар. 2021 г. 16:00:55

Я бы предложил добавить либо update_user_caches(get_user_by('id', $user_id)), либо clean_user_cache($user_id) после этого обновления, если вы используете wp_object_cache. Я на собственном опыте убедился, что прямое изменение записей пользователей в WP может привести к очень неожиданному поведению.

Dan B Dan B
13 мая 2024 г. 16:02:13
Показать остальные 4 комментариев
1

Вы также можете изменить user_nicename с помощью SQL-запроса. После этого все постоянные ссылки и другие функции будут работать корректно.

11 июн. 2014 г. 09:45:53
Комментарии

Вместо этого вы можете рассмотреть использование ID в качестве слага профиля вместо nice_name. Это гарантирует, что профиль будет иметь универсальный URL, и у вас не будет случайных 404 страниц (я предполагаю, что это лучше для SEO).

amarinediary amarinediary
27 мар. 2021 г. 16:06:35
0

В дополнение к ответу Krzysiek Dróżdż.

Если вы не хотите, чтобы пользователи выходили из системы после изменения user_login, вам нужно выполнить следующее, чтобы пользователь оставался в системе с новыми данными:

clean_user_cache($user->ID);
wp_clear_auth_cookie();
wp_set_current_user($user->ID);
wp_set_auth_cookie($user->ID, true);
update_user_caches($user);
2 мая 2024 г. 23:06:56
0

Вы должны использовать фильтр для изменения $data при обновлении пользователя, нельзя использовать действие, которое обычно применяется для хука при обновлении пользователя.

Также необходимо перенести несколько мер безопасности и проверок, которые WordPress выполняет в своём коде, в вашу новую функцию.

Что можно сделать:

  1. Подключиться к фильтру wp_pre_insert_user_data. Убедитесь, что делаете это только при наличии соответствующих прав: add_filter( 'wp_pre_insert_user_data', 'prefix_change_user_login', 10, 4 );
  2. Теперь создайте функцию prefix_change_user_login, где вы получите $data, user_login из $_POST и пропустите его через ряд валидаций и санитаций (подробнее см. https://github.com/WordPress/wordpress-develop/blob/bb27ffce6c3b10738008f9a054782945a0744960/src/wp-includes/user.php#L2076-L2498)
  3. Кроме того, вам нужно разрешить редактирование поля логина пользователя в экране редактирования пользователя в админке WordPress или передать это значение в ваш код другим способом.

Пример такой функции:

    /**
     * Обновление логина пользователя
     *
     * @since x.x.x
     * @param array    $data {
     *     Значения и ключи для пользователя.
     *
     *     @type string $user_login      Логин пользователя. Включается только если $update == false
     *     @type string $user_pass       Пароль пользователя.
     *     @type string $user_email      Email пользователя.
     *     @type string $user_url        URL пользователя.
     *     @type string $user_nicename   Красивое имя пользователя. По умолчанию — URL-безопасная версия логина.
     *     @type string $display_name    Отображаемое имя пользователя.
     *     @type string $user_registered MySQL-метка времени, описывающая момент регистрации пользователя. По умолчанию —
     *                                   текущая UTC-метка времени.
     * }
     * @param bool     $update   Обновляется ли пользователь, а не создаётся.
     * @param int|null $user_id  ID пользователя для обновления или NULL, если пользователь создаётся.
     * @param array    $userdata Необработанный массив данных, переданный в wp_insert_user().
     */
    function prefix_change_user_login( $data, $update, $user_id, $userdata ){

        // НЕ ЗАБУДЬТЕ ДОБАВИТЬ ПРОВЕРКУ NONCE И REFERRER ЗДЕСЬ!!!!

        $sanitized_user_login = sanitize_user( wp_unslash( $_POST['user_login'] ), true ); // В нашем случае получаем новый логин из значения формы в админке. Если у вас другой случай использования — адаптируйте!

        /**
         * Фильтрует имя пользователя после его санитарии.
         *
         * Этот фильтр вызывается перед созданием или обновлением пользователя.
         *
         * @since 2.0.3
         *
         * @param string $sanitized_user_login Имя пользователя после санитарии.
         */
        $pre_user_login = apply_filters( 'pre_user_login', $sanitized_user_login );
        $illegal_logins = (array) apply_filters( 'illegal_user_logins', array() );

        // Удаляем любые непечатаемые символы из строки логина, чтобы проверить, не осталась ли она пустой.
        $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 ) ); // Кто знает, что курили разработчики WP, когда решили сделать nicename на 10 символов короче логина?
        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 позволяет 50 символов. Вычитаем один для дефиса плюс длину суффикса.
                $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;

    }

Теперь это позволит вам обновлять логин пользователя, а также обновлять красивое имя пользователя (используемое, например, в архивах).

Конечно, это всё ещё требует "включения" редактирования в области админки WordPress, но это не должно быть слишком сложно.

Обратите внимание, что если в приведённом выше коде произойдёт ошибка (логин уже существует и т.д.), НИКАКАЯ ошибка не отобразится — вместо этого пользователь просто обновится, вернувшись к предыдущему значению.

Также учтите, что хотя этот код протестирован, вы используете его на свой страх и риск, и у WordPress ЕСТЬ ПРИЧИНЫ не разрешать обновление логина пользователя.

14 апр. 2023 г. 08:14:18