Как проверить, залогинен ли пользователь (не текущий)?
Мне нужно отображать статус онлайн (онлайн/оффлайн) для каждой страницы автора (пользовательский шаблон страницы автора).
Функция is_user_logged_in() работает только для текущего пользователя, и я не могу найти подходящий способ проверить статус текущего автора, например, is_author_logged_in().
Есть идеи?
Ответ
One Trick Pony любезно предоставил код для двух-трёх функций с использованием transient (временных данных), которые я раньше не использовал.
http://codex.wordpress.org/Transients_API
Добавьте это в functions.php:
add_action('wp', 'update_online_users_status');
function update_online_users_status(){
if(is_user_logged_in()){
// получаем список онлайн-пользователей
if(($logged_in_users = get_transient('users_online')) === false) $logged_in_users = array();
$current_user = wp_get_current_user();
$current_user = $current_user->ID;
$current_time = current_time('timestamp');
if(!isset($logged_in_users[$current_user]) || ($logged_in_users[$current_user] < ($current_time - (15 * 60)))){
$logged_in_users[$current_user] = $current_time;
set_transient('users_online', $logged_in_users, 30 * 60);
}
}
}
Добавьте это в author.php (или другой шаблон страницы):
function is_user_online($user_id) {
// получаем список онлайн-пользователей
$logged_in_users = get_transient('users_online');
// онлайн, если пользователь в списке и последняя активность была менее 15 минут назад
return isset($logged_in_users[$user_id]) && ($logged_in_users[$user_id] > (current_time('timestamp') - (15 * 60)));
}
$passthis_id = $curauth->ID;
if(is_user_online($passthis_id)){
echo 'Пользователь онлайн.';}
else {
echo 'Пользователь не онлайн.';}
Второй ответ (не рекомендуется)
Этот ответ приведён для справки. Как отметил One Trick Pony, этот подход нежелателен, так как обновляет базу данных при каждой загрузке страницы. При дальнейшем анализе код, похоже, определял только статус текущего пользователя, а не сравнивал его с текущим автором.
1) Установите этот плагин: http://wordpress.org/extend/plugins/who-is-online/
2) Добавьте следующее в шаблон страницы:
// Устанавливаем переменную $curauth
if(isset($_GET['author_name'])) :
$curauth = get_userdatabylogin($author_name);
else :
$curauth = get_userdata(intval($author));
endif;
// Определяем ID страницы просматриваемого автора
$authortemplate_id = $curauth->ID;
// Подключаемся к базе данных
global $wpdb;
// Определяем таблицу как переменную
$who_is_online_table = $wpdb->prefix . 'who_is_online';
// Запрос: подсчитываем количество user_id (из плагина), совпадающих с ID автора (страницы автора)
$onlinestatus_check = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM ".$who_is_online_table." WHERE user_id = '".$authortemplate_id."';" ) );
// Если найдено совпадение...
if ($onlinestatus_check == "1"){
echo "<p>Пользователь <strong>онлайн</strong> сейчас!</p>";
}
else{
echo "<p>Пользователь сейчас <strong>оффлайн</strong>.</p>";
}

Я бы использовал транзиенты для этого:
создайте функцию обновления статуса "пользователь онлайн", которую вы подключите к хуку
init
; она может выглядеть примерно так:// получаем список активных пользователей $logged_in_users = get_transient('online_status'); // получаем ID текущего пользователя $user = wp_get_current_user(); // проверяем, нужно ли обновлять статус текущего пользователя; // обновление требуется, если его нет в списке $no_need_to_update = isset($logged_in_users[$user->ID]) // или если его "последняя активность" была менее чем... 15 минут назад && $logged_in_users[$user->ID] > (time() - (15 * 60)); // обновляем список, если нужно if(!$no_need_to_update){ $logged_in_users[$user->ID] = time(); set_transient('online_status', $logged_in_users, $expire_in = (30*60)); // 30 минут }
Этот код будет выполняться при каждой загрузке страницы, но транзиент будет обновляться только при необходимости. Если у вас много пользователей онлайн, вы можете увеличить временной интервал "последней активности", чтобы уменьшить количество записей в БД, но 15 минут вполне достаточно для большинства сайтов...
теперь, чтобы проверить, находится ли пользователь онлайн, просто посмотрите в этот транзиент, как вы делали выше:
// получаем список активных пользователей $logged_in_users = get_transient('online_status'); // например, на странице автора $user_to_check = get_query_var('author'); $online = isset($logged_in_users[$user_to_check]) && ($logged_in_users[$user_to_check] > (time() - (15 * 60)));
Транзиент истекает через 30 минут, если нет никакой активности. Но если у вас постоянно есть пользователи онлайн, он не истечет, поэтому вы можете периодически очищать этот транзиент, подключив другую функцию к дважды в день событию или чему-то подобному. Эта функция будет удалять старые записи $logged_in_users
...

Транзиенты для меня в новинку. Спасибо за код. Не могу реализовать первый шаг. Я скопировал ваш первый блок кода и вставил его в function user_online_update() {
[ВАШ КОД] }add_action('init', 'user_online_update');
в мой файл functions.php — получаю ошибку сервера, что говорит о том, что что-то не парсится правильно или я неправильно понял ваши инструкции.

+1 за предложение использовать транзиенты. Немногие о них знают.

@Dominor: полный код.

@OneTrickPony: Я добавил действие в functions.php. Куда добавить вторую функцию (см. строку 27 вашего полного кода)? Я пробовал authors.php, а затем functions.php, но безрезультатно. Я попытался использовать условие из строки 25 вашего полного кода. Каждый раз страница возвращает ошибку сервера или не обрабатывает ничего на моей странице после вашего кода. Я удалил свой исходный код и отключил плагин "Who is online?". Что я упускаю?

замените $time_limit
на 15
и убедитесь, что вы правильно открыли/закрыли php-теги...

Спасибо, наконец разобрался. Я заменил переменную $time_limit. Код в PASTEBIN, в строке 27, похоже, не хватало скобки (круглой и квадратной) для работы. Я протестировал, войдя в три-четыре аккаунта с использованием отдельных браузеров для каждого. Вроде работает отлично. Спасибо! Я добавил итоговый код в вопрос (выше).

Насколько мне известно, нет способа сделать это с помощью встроенных функций WordPress, но пусть это вас не останавливает; напишите плагин!
Один из способов — создать новую таблицу в базе данных, которая просто отслеживает последнее время активности пользователя на сайте. Вы также можете добавить страницу настроек для вашего плагина, которая определяет, как долго зарегистрированного пользователя следует считать "авторизованным".
Это можно реализовать с помощью хука WordPress. Я бы начал с подключения к процессу входа, чтобы после авторизации пользователя ваш плагин записывал время в базу данных. Затем можно добавить другие функции, например, устанавливать статус 'не в сети', если пользователь выходит, или 'бездействует', если время его входа было более двух часов назад.
Возникнет проблема, если пользователь авторизован и активен на сайте, но превысил двухчасовой лимит. В этом случае потребуется подключиться к разделу wp-admin, чтобы любое действие пользователя в административной панели обновляло время в вашей базе данных.
Далее, для записей потребуется выполнить две вещи: получить автора текущей записи:
<?php $user_login = the_author_meta( $user_login ); ?>
а затем запросить вашу базу данных, чтобы проверить, авторизован ли пользователь:
<?php if your_plugin_function($user_login)... ?>
...вывести что-то...

На основе вашего решения я нашел плагин, который создает таблицу и позволяет задавать время простоя через настройки. После просмотра файлов плагина я не уверен, как изменить код, чтобы выводить статус онлайн/оффлайн в моем шаблоне страницы автора. Если бы вы могли взглянуть на файлы плагина и указать правильное направление, я был бы признателен: http://wordpress.org/extend/plugins/who-is-online/ (Используя ваши инструкции, я пока попробую зайти как можно дальше, используя хук в моем файле functions.php)

Я решил пересмотреть данный ответ и адаптировать его с учетом комментариев.
В комментариях обсуждалась идея ежедневной очистки временных данных. Как отметил @onetrickpony, мы можем использовать wp_schedule_event()
для настройки ежедневного сброса.
Я решил реализовать простой способ получения списка пользователей, находящихся в сети и недавно вышедших из нее.
Вся система построена на объектно-ориентированном подходе и упакована в класс.
Содержание |
---|
Получение статуса активности конкретного пользователя по его ID. |
Получение массива всех пользователей, находящихся в сети. |
Получение массива всех пользователей, недавно вышедших из сети. |
Настройка ежедневного события для удаления временных данных активности пользователей. |
Упаковка всего в удобный плагин. |
if ( ! class_exists( 'WPC_User_Activity_Monitoring' ) ) {
class WPC_User_Activity_Monitoring {
/**
* @var Integer Период неактивности пользователя в минутах.
*/
private const USER_INACTIVITY_MARGIN = 10 * MINUTE_IN_SECONDS;
/**
* @var Integer Время хранения временных данных в минутах.
*/
private const TRANSIENT_SELF_CLEAR = 30 * MINUTE_IN_SECONDS;
/**
* Привязывает методы к наборам действий.
*
* @since 1.0.0
*/
public function __construct() {
add_action( 'init', array( $this, 'wpc_user_activity_monitoring_transient' ) );
}
/**
* Установка и обновление временных данных мониторинга активности пользователей WPC при взаимодействии с сервером.
*
* @since 1.0.0
*
* @param Integer $user_id ID пользователя.
*
* @return Bool True, если пользователь онлайн.
*/
public function wpc_user_activity_monitoring_transient() {
if ( is_user_logged_in() ) {
$wpc_user_activity_monitoring_transient = get_transient( 'wpc_user_activity_monitoring_transient' );
if ( empty( $wpc_user_activity_monitoring_transient ) ) {
$wpc_user_activity_monitoring_transient = array();
};
$user_id = get_current_user_id();
$timestamp = current_time( 'timestamp' );
if ( empty( $wpc_user_activity_monitoring_transient[$user_id] ) || ( $wpc_user_activity_monitoring_transient[$user_id] < ( $timestamp - self::USER_INACTIVITY_MARGIN ) ) ) {
$wpc_user_activity_monitoring_transient[$user_id] = $timestamp;
set_transient( 'wpc_user_activity_monitoring_transient', $wpc_user_activity_monitoring_transient, self::TRANSIENT_SELF_CLEAR );
};
};
}
/**
* Получение статуса активности конкретного пользователя по его ID.
*
* @since 1.0.0
*
* @param Integer $user_id ID пользователя.
*
* @return Bool True, если пользователь онлайн.
*/
public function is_user_currently_online( $user_id ) {
$wpc_user_activity_monitoring_transient = get_transient( 'wpc_user_activity_monitoring_transient' );
if ( ! isset( $wpc_user_activity_monitoring_transient[$user_id] ) {
return;
};
if ( $wpc_user_activity_monitoring_transient[$user_id] > ( current_time( 'timestamp' ) - self::USER_INACTIVITY_MARGIN ) ) {
return isset( $wpc_user_activity_monitoring_transient[$user_id] );
};
}
/**
* Получение массива всех пользователей, находящихся в сети.
*
* @since 1.0.0
*
* @param Integer $nusers Количество онлайн-пользователей для получения.
*
* @return Array Массив ID пользователей, находящихся в сети.
*/
public function get_currently_online_nusers() {
$wpc_user_activity_monitoring_transient = array_reverse( get_transient( 'wpc_user_activity_monitoring_transient' ), true );
$currently_online_nusers = array();
foreach ( $wpc_user_activity_monitoring_transient as $user_id => $timestamp ) {
if ( $timestamp > ( current_time( 'timestamp' ) - self::USER_INACTIVITY_MARGIN ) ) {
array_push( $currently_online_nusers, $user_id );
};
};
return $currently_online_nusers;
}
/**
* Получение массива всех пользователей, недавно вышедших из сети.
*
* @since 1.0.0
*
* @param Integer $nusers Количество недавно вышедших пользователей для получения.
*
* @return Array Массив ID пользователей, недавно вышедших из сети.
*/
public function get_recently_offline_nusers() {
$wpc_user_activity_monitoring_transient = array_reverse( get_transient( 'wpc_user_activity_monitoring_transient' ), true );
$recently_offline_nusers = array();
foreach ( $wpc_user_activity_monitoring_transient as $user_id => $timestamp ) {
if ( $timestamp < ( current_time( 'timestamp' ) - self::USER_INACTIVITY_MARGIN ) ) {
array_push( $recently_offline_nusers, $user_id );
};
};
return $recently_offline_nusers;
}
};
$wpc_user_activity_monitoring = new WPC_User_Activity_Monitoring();
};
/**
* Настройка ежедневного события, срабатывающего в 23:59:00 для удаления временных данных мониторинга активности пользователей WPC.
*
* @since 1.0.0
*/
if ( ! wp_next_scheduled ( 'schedule_event_delete_wpc_user_activity_monitoring_transient' ) ) {
wp_schedule_event( strtotime( '23:59:00' ), 'daily', 'schedule_event_delete_wpc_user_activity_monitoring_transient' );
};
/**
* Удаление временных данных мониторинга активности пользователей WPC.
*
* @since 1.0.0
*/
add_action( 'schedule_event_delete_wpc_user_activity_monitoring_transient', 'delete_wpc_user_activity_monitoring_transient' );
if ( ! function_exists( 'delete_wpc_user_activity_monitoring_transient' ) ) {
function delete_wpc_user_activity_monitoring_transient() {
delete_transient( 'wpc_user_activity_monitoring_transient' );
};
};
Упаковка всего в удобный плагин.
Я также создал плагин для простой реализации. Он имеет открытый исходный код на GitHub @ https://github.com/amarinediary/WPC-User-Activity-Monitoring. Там есть дополнительная документация и функциональность.
