Как создать собственную страницу профиля пользователя в WP

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

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

Даже на англоязычных сайтах я ничего не нашел (не знаю, может искал плохо), конечно некоторые решения имелись, но все они были плагинами.

Пример произвольной страницы профиля пользователя на одном из созданных мной сайтов.
Пример произвольной страницы профиля пользователя на одном из созданных мной сайтов.

Шаг 1. Шаблон страницы

Кое-что про шаблоны страниц я тоже уже писал, поэтому сейчас сразу перехожу к коду.

<?php
/*
 * Template name: Шаблон профиля пользователя
 */
global $user_ID;
 
// если пользователь не авторизован, отправляем его на страницу входа
if( !$user_ID ) {
	header('location:' . site_url() . '/wp-login.php');
	exit;
} else {
	$userdata = get_user_by( 'id', $user_ID );
}
?><html>
<body>
<?php
// после сохранения профиля и смены пароля понадобятся уведомления
// если уведомлений больше двух, то оптимальнее их будет вывести через switch
if( isset($_GET['status']) ) :
	switch( $_GET['status'] ) :
		case 'ok':{
			echo '<div class="success">Сохранено.</div>';
			break;
		}
		case 'exist':{
			echo '<div class="error">Пользователь с указанным email уже существует.</div>';
			break;
		}
		case 'short':{
			echo '<div class="error">Пароль слишком короткий.</div>';
			break;
		}
		case 'mismatch':{
			echo '<div class="error">Пароли не совпадают.</div>';
			break;
		}
		case 'wrong':{
			echo '<div class="error">Старый пароль неверен.</div>';
			break;
		}
		case 'required':{
			echo '<div class="error">Пожалуйста, заполните все обязательные поля.</div>';
			break;
		}
	endswitch;
endif;
 
// profile-update.php - это файл, который находится в папке с темой и обрабатывает сохранение, его содержимое будет в следующем шаге
?>
<form action="<?php echo get_stylesheet_directory_uri() ?>/profile-update.php" method="POST">
	<input type="text" name="first_name" placeholder="Имя" value="<?php echo $userdata->first_name ?>" />
	<input type="text" name="last_name" placeholder="Фамилия" value="<?php echo $userdata->last_name ?>" />
	<input type="text" name="city" placeholder="Город" value="<?php echo get_user_meta($user_ID, 'city', true ) ?>" />
	<input type="email" name="email" placeholder="Email" value="<?php echo $userdata->user_email ?>" />
 
	<input type="password" name="pwd1" placeholder="Старый пароль" />
	<input type="password" name="pwd2" placeholder="Новый пароль" />
	<input type="password" name="pwd3" placeholder="Повторите новый пароль" />
 
	<button>Сохранить</button>
</form>
</body>
</html>

Шаг 2. PHP-файл для обработки сохраняемых данных

Это и есть содержимое файла profile-update.php, который в прошлом шаге мы решили разместить прямо в папке с темой.

<?php
// $_SERVER['HTTP_REFERER'] - полный URL страницы, откуда пришел пользователь
// $url[0] - без GET параметров
// это нам понадобится для правильных редиректов
$url = explode("?",$_SERVER['HTTP_REFERER']);
 
// подключаем WordPress
// тут указан правильный путь, если profile-update.php находится непосредственно в папке с темой
require_once( dirname(__FILE__) . '/../../../wp-load.php' );
 
// если не авторизован, просто выходим из файла
if( !is_user_logged_in() ) exit;
 
// получаем объект пользователя с необходимыми данными
$user_ID = get_current_user_id();
$user = get_user_by( 'id', $user_ID );
 
 
// сначала обработаем пароли, ведь если при сохранении пользователь ничего не указал ни в одном поле пароля, то пропускаем эту часть
if( $_POST['pwd1'] || $_POST['pwd2'] || $_POST['pwd3'] ) {
 
	// при этом пользователь должен заполнить все поля
	if( $_POST['pwd1'] && $_POST['pwd2'] && $_POST['pwd3'] ) {
 
		// сначала проверяем соответствие нового пароля и его подтверждения
		if( $_POST['pwd2'] == $_POST['pwd3'] ){
 
			// пароль из двух символов нам не нужен, минимум 8
			if( strlen( $_POST['pwd2'] ) < 8 ) {
				// если слишком короткий - перенаправляем
				header('location:' . $url[0] . '?status=short');
				exit;
			}
 
			// и самое главное - проверяем, правильно ли указан старый пароль
			if( wp_check_password( $_POST['pwd1'], $user->data->user_pass, $user->ID) ) {
				// если да, меняем на новый и заново авторизуем пользователя
				wp_set_password( $_POST['pwd2'], $user_ID );
				$creds['user_login'] = $user->user_login;
				$creds['user_password'] = $_POST['pwd2'];
				$creds['remember'] = true;
				$user = wp_signon( $creds, false );
			} else {
				// если нет, перенаправляем на ошибку
				header('location:' . $url[0] . '?status=wrong');
				exit;
			}
 
		} else {
			// новый пароль и его подтверждение не соответствуют друг другу
			header('location:' . $url[0] . '?status=mismatch');
			exit;
		}
 
	} else {
		// не все поля заполнены - перенеправляем
		header('location:' . $url[0] . '?status=required');
		exit;
	}
}
 
// допустим, что Имя, Фамилия и Емайл - обязательные поля, Город - не обязательное
if( $_POST['first_name'] && $_POST['last_name'] && is_email($_POST['email']) ) {
 
	// если пользователь указал новый емайл, а кто-то уже под ним зареган - отправляем на ошибку
	if( email_exists( $_POST['email'] ) && $_POST['email'] != $user->user_email ) {
		header('location:' . $url[0] . '?status=exist');
		exit;
	}
 
	// обновляем данные пользователя
	wp_update_user( array( 
			'ID' => $user_ID, 
			'user_email' => $_POST['email'],
			'first_name' => $_POST['first_name'],
			'last_name' => $_POST['last_name'],
			'display_name' => $_POST['first_name'] . ' ' . $_POST['last_name'] ));
 
	// ну и город не забываем обновить
	update_user_meta( $user_ID, 'city', $_POST['city']);
} else {
	// не все поля заполнены - перенеправляем
	header('location:' . $url[0] . '?status=required');
	exit;
}
 
 
// если выполнение кода дошло до сюда, то следовательно всё ок
header('location:' . $url[0] . '?status=ok');
exit;

Если у вас есть вопросы по работе кода или предложения по его доработке, прошу вас проследовать в комментарии 🙂

Миша Рудрастых Разработчик WordPress WooCommerce

Миша Рудрастых

Впервые познакомился с WordPress в 2009 году, и после двух лет мучений с Joomla и самописными движками это был просто бальзам на душу. С 2014 года меня можно встретить на WordCamp — официальной конфе по WP в Москве, иногда там выступаю. Также в настоящее время веду курсы по WordPress в Epic Skills в Питере.

Почти все функции, использованные в коде статьи