WordPress-Benutzernamen programmatisch bearbeiten
Veröffentlicht: – Kommentar hinterlassen
Während des Hinzufügens eines WordPress-Benutzers gibt es keine Information darüber, dass der Benutzername später nicht geändert werden kann. Aber was, wenn das erforderlich ist? Das Feld auf der Seite zum Bearbeiten des Profils ist deaktiviert und auch seine Aktivierung über die Entwicklerwerkzeuge trickst WordPress nicht aus – ja, das habe ich getestet. Aber auch die Verwendung von wp_update_user
aktualisiert den Benutzernamen nicht, da das Feld user_login
explizit von der Aktualisierung ignoriert wird.
Du könntest den Benutzernamen einfach in der Datenbank aktualisieren, wenn du darauf Zugriff hast. Da dies aber nicht die Caches zurücksetzt, ist das keine Option für Installationen mit einem persistenten Objekt-Cache wie Redis, sodass dort der Benutzername nicht aktualisiert werden würde. Daher habe ich nach einer Lösung gesucht.
In meinem Fall hatten alle Benutzernamen die Struktur vorname.nachname@domain.tld
, die von einem Single-Sign-On-Plugin (SSO) kamen. Da wir auf ein anderes SSO-Plugin mit der Struktur vorname.nachname
für die Benutzernamen wechselten, müssen wir das @domain.tld
loswerden.
Zusätzlich müssen wir die Netzwerk-Administratoren aktualisieren, da wir eine Multisite haben. Diese Information ist in der Netzwerk-Option site_admins
gespeichert und beinhaltet eine Liste mit Benutzernamen (wer auch immer darauf kam, dass es eine gute Idee ist, die Benutzernamen statt die Benutzer-IDs zu speichern 🥲).
So sieht mein Code aus:
<?php
global $wpdb;
$site_admins = [];
if ( \is_multisite() ) {
$site_admins = \get_site_option( 'site_admins' );
}
$users = \get_users( [
'blog_id' => 0,
'fields' => [
'ID',
'user_email',
'user_login',
],
] );
foreach ( $users as $user ) {
// do our desired replacements
if ( ! \str_contains( $user->user_login, '@domain.tld' ) && \str_contains( $user->user_email, '@domain.tld' ) ) {
$new_username = \str_replace( '@domain.tld', '', $user->user_email );
}
else {
$new_username = \str_replace( '@domain.tld', '', $user->user_login );
}
// update user only if if the username changes
if ( $user->user_login !== $new_username ) {
echo 'Change ' . \esc_html( $user->user_login ) . ' to ' . \esc_html( $new_username ) . \PHP_EOL;
// check if current user is a super admin
if ( \in_array( $user->user_login, $site_admins, true ) ) {
$user_loginname = $user->user_login;
// replace this user's name in the list of super admins
$site_admins = \array_map(
function( $username ) use ( $user_loginname, $new_username ) {
return $username === $user_loginname ? $new_username : $username;
},
$site_admins
);
\update_site_option( 'site_admins', $site_admins );
}
// update the user in the database
$wpdb->update(
$wpdb->users,
[ 'user_login' => $new_username ],
[ 'ID' => $user->ID ]
);
// invalidate object cache
\clean_user_cache( $user->ID );
}
}
Code-Sprache: PHP (php)
Da man nicht die integrierte Funktion zum Aktualisieren des Benutzernamens verwenden kann, müssen wir das Datenbank-Statement selbst angeben. Zusätzlich benötigen wir clean_user_cache
, um den Objekt-Cache für den angegebenen Benutzer zu leeren.
Ich habe diesen Code in einer Datei gespeichert und ihn direkt über WP-CLIs wp oval-file
ausgeführt. In einer Multisite muss sie nicht für jede Website ausgeführt werden, da die Benutzerdaten global gespeichert werden.