Для примера возьмем статейный сайт, на нём нужно сделать счетчик просмотров статей, с выводом результатов за день, неделю, месяц и построить график посещаемости.
Для хранения просмотров нужно создать таблицу `visits` в БД:
CREATE TABLE IF NOT EXISTS `visits` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`page_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
`counter` int(11) UNSIGNED NOT NULL,
`date` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Где:
page_id
– ID страницы,counter
– количество просмотров,date
– дата в форматеYYYY-MM-DD
.
Просмотры будут хранится в виде счетчика за день, таким образом получится сэкономить на количестве записей в таблице и ускорить последующие SQL-запросы к ней.
В обработчике вывода статей нужно добавить код для добавления данных в созданную таблицу.
// ID статьи
$post_id = 123;
// Подключение к БД (далее в примерах его не будет).
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль');
$sth = $dbh->prepare("SELECT * FROM `visits` WHERE `page_id` = ? AND `date` = CURDATE()");
$sth->execute(array($post_id));
$res = $sth->fetch(PDO::FETCH_ASSOC);
if (empty($res)) {
$sth = $dbh->prepare("INSERT INTO `visits` SET `page_id` = ?, `counter` = 1, `date` = CURDATE()");
$sth->execute(array($post_id));
} else {
$sth = $dbh->prepare("UPDATE `visits` SET `counter` = `counter` + 1 WHERE `id` = ?");
$sth->execute(array($res['id']));
}
Если один пользователь обновит страницу несколько раз, то все просмотры будут зачтены. Избежать этого можно добавив проверку – дополнительно хранить user agent последнего пользователя в отдельном поле БД и при обновлении проверять его.
Также можно исключить просмотры поисковиков и других ботов с помощью функции is_bot().
Теперь просмотры добавляются в БД:
Через некоторое время можно сформировать результаты:
Просмотры за день
$post_id = 123;
$sth = $dbh->prepare("SELECT `counter` AS `views` FROM `visits` WHERE `post_id` = ? AND `date` = CURDATE()");
$sth->execute(array($post_id));
$res = $sth->fetch(PDO::FETCH_ASSOC);
echo $res['views'];
Неделя, месяц, год
$post_id = 123;
$date = date('Y-m-d', strtotime('-7 days')); // -1 month, -1 year
$sth = $dbh->prepare("SELECT SUM(`counter`) AS `views` FROM `visits` WHERE `item_id` = ? AND `date` > ?");
$sth->execute(array($post_id, $date));
$res = $sth->fetch(PDO::FETCH_ASSOC);
echo $res['views'];
Интервал между датами
$post_id = 123;
$date_start = date('Y-m-d', strtotime('01.09.2019'));
$date_end = date('Y-m-d', strtotime('01.10.2019'));
$sth = $dbh->prepare("SELECT SUM(`counter`) AS `views` FROM `visits` WHERE `item_id` = :id AND `date` BETWEEN :start AND :end");
$sth->execute(array('id' => $post_id, 'start' => $date_start, 'end' => $date_end));
$res = $sth->fetch(PDO::FETCH_ASSOC);
echo $res['views'];
За всё время
Сформируем график просмотров статьи с помощью плагина диаграмм morris.js. В PHP получим данные, сформируем массив по дням и выведем объектом в JS.
<?php
$sth = $dbh->prepare("SELECT * FROM `visits` WHERE `post_id` = ? ORDER BY `date`");
$sth->execute(array($post_id));
$res = $sth->fetchAll(PDO::FETCH_ASSOC);
$list = array();
foreach ($res as $row) {
$list[] = array('year' => date('d.m.Y', strtotime($row['date'])), 'value' => $row['counter']);
}
?>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
<div id="visits" style="height: 250px;"></div>
<script>
new Morris.Bar({
element: 'visits',
data: <?php echo json_encode($list); ?>,
xkey: 'year',
ykeys: ['value'],
labels: ['Просмотры']
});
</script>