Разработка на PHP: Как правильно реализовать обновление времени последней активности пользователя (last_activity) через PDO::prepare?
Обновление времени последней активности пользователя (поле `last_activity`) — стандартная задача при разработке веб-приложений на PHP. Правильная реализация через `PDO::prepare` обеспечивает безопасность, защиту от SQL-инъекций и производительность.
## Базовая реализация
Первым делом необходимо установить PDO-соединение с базой данных:
php
$dsn = ‘mysql:host=localhost;dbname=mydb;charset=utf8mb4’;
$pdo = new PDO($dsn, ‘username’, ‘password’, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
Затем выполняем обновление `last_activity`:
php
function updateLastActivity(PDO $pdo, int $userId): bool {
$sql = ‘UPDATE users SET last_activity = NOW() WHERE id = :user_id’;
$stmt = $pdo->prepare($sql);
$stmt->bindValue(‘:user_id’, $userId, PDO::PARAM_INT);
return $stmt->execute();
}
## Почему важно использовать PDO::prepare
— **Защита от SQL-инъекций**: параметризованные запросы не позволяют злоумышленнику подставить вредоносный SQL-код.
— **Повторное использование**: подготовленный запрос можно выполнять многократно с разными параметрами без повторной компиляции.
— **Читаемость**: код становится чище и понятнее.
## Хранение времени: NOW() vs PHP
Можно использовать как серверное время MySQL (`NOW()`), так и время из PHP:
php
// Через PHP
$now = date(‘Y-m-d H:i:s’);
$sql = ‘UPDATE users SET last_activity = :now WHERE id = :user_id’;
$stmt = $pdo->prepare($sql);
$stmt->bindValue(‘:now’, $now, PDO::PARAM_STR);
$stmt->bindValue(‘:user_id’, $userId, PDO::PARAM_INT);
$stmt->execute();
Рекомендуется использовать `NOW()` на стороне MySQL, чтобы избежать расхождений при разных часовых поясах серверов.
## Оптимизация: не обновлять слишком часто
Если `last_activity` обновляется при каждом запросе, это создаёт нагрузку на БД. Оптимальный подход — обновлять не чаще одного раза в несколько минут:
php
function updateLastActivityThrottled(PDO $pdo, int $userId, int $intervalSeconds = 300): bool {
$sql = ‘UPDATE users SET last_activity = NOW()
WHERE id = :user_id
AND (last_activity IS NULL OR last_activity prepare($sql);
$stmt->bindValue(‘:user_id’, $userId, PDO::PARAM_INT);
$stmt->bindValue(‘:interval’, $intervalSeconds, PDO::PARAM_INT);
return $stmt->execute();
}
## Индексирование поля last_activity
Если вы часто делаете выборки по полю `last_activity` (например, для поиска онлайн-пользователей), добавьте индекс:
sql
ALTER TABLE users ADD INDEX idx_last_activity (last_activity);
## Обработка ошибок
Всегда оборачивайте запросы в блок `try-catch`:
php
try {
updateLastActivity($pdo, $userId);
} catch (PDOException $e) {
error_log(‘Ошибка обновления last_activity: ‘ . $e->getMessage());
}
## Итог
Использование `PDO::prepare` для обновления `last_activity` — это безопасный, производительный и профессиональный подход. Применяйте параметризованные запросы, контролируйте частоту обновлений и не забывайте про индексы.
