Как создать профиль пользователя на фронтенде с человеко-понятным URL
Я хочу создать публичную страницу профиля пользователя на фронтенде с удобным URL в таком формате:
mysite.com/user/имяпользователя
Есть идеи, как этого достичь? Я понимаю, что это связано с правилами перезаписи URL, но не знаю, как это реализовать. Буду благодарен за ссылки или обучающие материалы по этой теме.
Спасибо!

Я обнаружил два способа реализации этого:
- Страница автора с пользовательским правилом перезаписи URL
- Пользовательские файлы шаблонов в сочетании с правилом перезаписи
Первый вариант проще в реализации, но может работать не во всех случаях (один из таких случаев я опишу далее).
Пользовательское правило перезаписи URL
Это решение я нашел несколько дней назад здесь: URL Rewriting
Вот код с комментариями:
// Определяем уровни авторов, которые хотим использовать
$custom_author_levels = array( 'user', 'leader' );
// При инициализации добавляем новый тег перезаписи author_level и добавляем его в свойство author_base wp_rewrite
add_action( 'init', 'wpleet_init' );
function wpleet_init()
{
global $wp_rewrite;
$author_levels = $GLOBALS['custom_author_levels'];
// Определяем тег и используем его в правиле перезаписи
add_rewrite_tag( '%author_level%', '(' . implode( '|', $author_levels ) . ')' );
$wp_rewrite->author_base = '%author_level%';
}
// Предыдущая функция создает лишние правила перезаписи author_name, которые не нужны.
// Эта функция проверяет и удаляет их
add_filter( 'author_rewrite_rules', 'wpleet_author_rewrite_rules' );
function wpleet_author_rewrite_rules( $author_rewrite_rules )
{
foreach ( $author_rewrite_rules as $pattern => $substitution ) {
if ( FALSE === strpos( $substitution, 'author_name' ) ) {
unset( $author_rewrite_rules[$pattern] );
}
}
return $author_rewrite_rules;
}
Затем вы можете использовать встроенный шаблон author.php, модифицируя его по своему усмотрению.
Обязательно ознакомьтесь с приведенной выше ссылкой, так как Jan Fabry отлично объясняет все детали.
Переменные запроса и шаблоны страниц
Для темы, над которой я работал, мне нужно было отображать пользовательскую страницу на основе значения пользовательского мета-поля (отдельного ID). Мой клиент не хотел, чтобы имя пользователя или его ID были видны публично, поэтому мы создали дополнительный уровень защиты.
Единственная проблема? На данный момент нет четкого способа использовать Rewrite API для запросов по мета-ключам/значениям. К счастью, решение нашлось.
В файле functions.php...
// Создаем переменную запроса, чтобы WP обрабатывал пользовательский URL /user/username
add_filter( 'query_vars', 'wpleet_rewrite_add_var' );
function wpleet_rewrite_add_var( $vars )
{
$vars[] = 'user';
return $vars;
}
Затем нужно создать новый тег перезаписи и правило, чтобы система знала, когда и как обрабатывать новую переменную запроса.
add_rewrite_tag( '%user%', '([^&]+)' );
add_rewrite_rule(
'^user/([^/]*)/?',
'index.php?user=$matches[1]',
'top'
);
После этого остается только "перехватить" момент, когда переменная запроса обрабатывается, и перенаправить на выбранный шаблон:
add_action( 'template_redirect', 'wpleet_rewrite_catch' );
function wpleet_rewrite_catch()
{
global $wp_query;
if ( array_key_exists( 'user', $wp_query->query_vars ) ) {
include (TEMPLATEPATH . '/user-profile.php');
exit;
}
}
Убедитесь, что вы создали файл user-profile.php.
В моем примере я создал третью функцию, которая сопоставляла "публичный ID пользователя" с реальным user_id через таблицу $wpdb->usermeta и передавала информацию в шаблон.
Если вам нужно создать шаблон, отличающийся от остальной темы, помните, что с get_header можно указать имя:
get_header( 'user' );
Это вызовет файл header-user.php.
Заключение
Оба варианта являются рабочими решениями. Второй предлагает дополнительный уровень "безопасности", так как не раскрывает ID пользователей или их имена, если другие люди смогут просматривать профили.
Надеюсь, это поможет. Если есть вопросы - задавайте.

@bybloggers Я знаю, что этот пост немного старый, но мне было интересно, не могли бы вы поделиться своей третьей функцией для передачи имени пользователя в URL шаблону?

@Pat Не уверен, где именно сейчас находится эта функция в моем коде (как вы сказали, это было давно), но формат будет очень похож на функцию wpleet_rewrite_catch(). Вместо array_key_exists('user') я проверял публичный ID пользователя, а затем искал в таблице wp_usermeta, какому пользователю этот публичный ID был присвоен. Надеюсь, алгоритм поможет, даже если код недоступен.

Я нашел это сегодня и внес некоторые изменения в код @bybloggers с той разницей, что вместо использования template_redirect я изменил запрос для отображения статической страницы. Это означает, что теперь вы можете добавить что угодно в шаблон страницы и использовать это на этой странице.
class ProfilePage {
function __construct() {
add_filter( 'init',array($this,'rw_init'));
add_filter( 'query_vars', array($this,'wpleet_rewrite_add_var') );
add_filter( 'request', array($this,'change_requests'));
}
function wpleet_rewrite_add_var( $vars ) {
$vars[] = 'usuario';
return $vars;
}
function rw_init(){
add_rewrite_tag( '%usuario%', '([^&]+)' );
add_rewrite_rule(
'^usuario/([^/]*)/?',
'index.php?usuario=$matches[1]',
'top'
);
}
function change_requests($query_vars) {
//переходим на определенную страницу, когда установлен ключ usuario
$query_vars['page_id'] = isset($query_vars['usuario']) ? 7581 : $query_vars['page_id'];
return $query_vars;
}
}
new ProfilePage();
Испанский -> usuario = пользователь <- Английский

Очень хорошо! Спасибо, что поделились. Я бы хотел сделать это более динамичным, и вы можете заменить id с помощью get_page_by_path('page-slug')->ID
. Также не забудьте использовать flush_rewrite_rules
, поэтому я бы добавил что-то вроде: add_action( 'after_switch_theme', 'flush_rewrite_rules' );

Это мой рабочий код, основанный на ответе @bybloggers (спасибо, кстати).
Я только что узнал, что не следует использовать хук template_redirect и затем завершать выполнение PHP, потому что некоторые вещи могут перестать работать из-за резкого прерывания выполнения кода PHP.
Объяснение можно найти здесь: https://markjaquith.wordpress.com/2014/02/19/template_redirect-is-not-for-loading-templates/
Таким образом, мы должны использовать хук template_include. С этим хуком нет необходимости использовать метод редиректа и выхода.
Ещё одно отличие в том, что мне нужно было использовать www.server.com/myaccount без /userid.
Вот код:
add_filter( 'query_vars', 'wp58683_userprofile_var' );
function wp58683_userprofile_var( $vars )
{
$vars[] = 'myprofile';
return $vars;
}
add_rewrite_tag( '%myprofile%', '([^&]+)' );
add_rewrite_rule(
'^myprofile/?',
'index.php?myprofile',
'top'
);
add_action( 'template_include', 'wp58683_userprofile_page' );
function wp58683_userprofile_page($original_template)
{
global $wp_query;
if ( array_key_exists( 'myprofile', $wp_query->query_vars ) ) {
if (is_user_logged_in() ){
return TEMPLATEPATH . '/user-profile.php';
}
}
else {
return $original_template;
}
}

Другой способ - использовать BuddyPress, который имеет эту функциональность встроенной, даже если у плагина есть еще больше возможностей, которые могут быть не нужны.
