Счетчик просмотров страниц с графиком

Для примера возьмем статейный сайт, на нём нужно сделать счетчик просмотров статей, с выводом результатов за день, неделю, месяц и построить график посещаемости.

Для хранения просмотров нужно создать таблицу `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;
SQL

Где:

  • 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']));
}
PHP

Если один пользователь обновит страницу несколько раз, то все просмотры будут зачтены. Избежать этого можно добавив проверку – дополнительно хранить 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'];
PHP

Неделя, месяц, год

$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'];
PHP

Интервал между датами

$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'];
PHP

За всё время

$post_id = 123;

$sth = $dbh->prepare("SELECT SUM(`counter`) AS `views` FROM `visits` WHERE `post_id` = :id");
$sth->execute(array('id' => $post_id));
$res = $sth->fetch(PDO::FETCH_ASSOC);
echo $res['views'];
PHP

Сформируем график просмотров статьи с помощью плагина диаграмм 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($res); ?>,
	xkey: 'year',
	ykeys: ['value'],
	labels: ['Просмотры']
});
</script>
HTML

Результат:

22.11.2019, обновлено 03.11.2020
9759

Комментарии 1

Денис Кораблев Денис Кораблев
14 февраля 2021 в 12:15
-3
Очень интересно, а вот как вывести график за прошедшие 7 дней?

, чтобы добавить комментарий.

Другие публикации

Работа с JSON в PHP
JSON (JavaScript Object Notation) – текстовый формат обмена данными, основанный на JavaScript, который представляет собой набор пар {ключ: значение}. Значение может быть массивом, числом, строкой и...
58848
+10
Обработка и вывод рейтинга в PHP
В продолжении статьи о верстки рейтинга, рассмотрим PHP-скрипты системы отзывов и рейтинга в интернет-магазине.
10915
+2
Обрезка текста для анонса
В случаях где анонсы не заполнены, сформировать и вывести их можно несколькими способами...
5024
+2
Автоматическое сжатие и оптимизация картинок на сайте
Изображения нужно сжимать для ускорения скорости загрузки сайта, но как это сделать? На многих хостингах нет...
15871
+8
Получить фото из Instagram без API
Так как Instagram и Fasebook ограничили доступ к API, а фото с открытого аккаунта всё же нужно периодически получать и...
19456
+6
Как вывести метки на Яндекс.Картах из MySQL+PHP
В статье рассмотрены примеры как вывести метку на карту из БД и вывод других объектов, которые находятся рядом.
13855
+7