Как сделать счетчик посетителей на сайте и получение статистики за разный период времени

PHP Класс Visitors Это простой пример, как сделать счетчик посетителей на сайте. 

Вот некоторые возможности данного класса, которые можно использоваться для получения статистики по своему сайту:

  • Получить статистику за сегодняшний день
  • Получить статистику за последние N дней
  • Получить статистику за определенный день
  • Получить статистику за текущий месяц
  • Получить статистику за последний месяц
  • Получить статистику за текущий год
  • Получить статистику за прошлый год
warning icon

Обратите внимание, что для работы этого класса используется RedBeanPHP.

Полный код класса

class Visitors
{
    public $ip;
    public $date;
    public $user_agent;

    public function __construct()
    {
        // получаем IP адрес, дату и user agent посетителя при создании объекта
        $this->ip = $_SERVER['REMOTE_ADDR'];
        $this->date = date('Y-m-d');
        $this->user_agent = $_SERVER['HTTP_USER_AGENT'];
    }

    public function trackingVisitors()
    {
        // проверяем, является ли посетитель ботом по его user agent
        if(!$this->isBot($this->user_agent)) {
            // ищем посетителя в базе данных по его IP
            $visitor = R::findOne('visitors', 'ip = ?', [$this->ip]);

            // если посетителя нет в базе, создаем нового и устанавливаем для него начальные значения
            if (!$visitor) {
                $visitor = R::dispense('visitors'); // создаем нового посетителя
                $visitor->ip = $this->ip;
                $visitor->date = $this->date;
                $visitor->user_agent = $this->user_agent;
                $visitor->views = 1;  // начинаем отсчет просмотров с 1
            } else {
                // если посетитель уже есть в базе, обновляем данные посещения
                // и увеличиваем количество просмотров
                $visitor->date = $this->date;
                $visitor->user_agent = $this->user_agent;
                $visitor->views = $visitor->views + 1;
            }

            // сохраняем изменения в объекте посетителя
            R::store($visitor);
        }
    }

    public function countUniqueVisitors()
    {
        // получаем количество уникальных посетителей (по уникальным IP адресам)
        $uniqueVisitors = R::getAll('SELECT COUNT(DISTINCT ip) as unique_visitors FROM visitors');

        return $uniqueVisitors[0]['unique_visitors'];
    }

    public function getStatistics($daysInterval)
    {
        // получаем статистику за заданный интервал времени (в днях)
        $daysInterval = intval($daysInterval);
        $periodViews = R::getCell('SELECT SUM(views) FROM visitors WHERE date >= DATE_SUB(CURDATE(), INTERVAL ? DAY)', [$daysInterval]);
        $periodVisitors = R::count('visitors', 'date >= DATE_SUB(CURDATE(), INTERVAL ? DAY)', [$daysInterval]);

        return array(
            'periodViews' => $periodViews,
            'periodVisitors' => $periodVisitors,
        );
    }

    public function getMonthStatistics($startDate, $endDate)
    {
        $periodViews = R::getCell('SELECT SUM(views) FROM visitors WHERE date BETWEEN ? AND ?', [$startDate, $endDate]);
        $periodVisitors = R::count('visitors', 'date BETWEEN ? AND ?', [$startDate, $endDate]);

        return array(
            'periodViews' => $periodViews,
            'periodVisitors' => $periodVisitors,
        );
    }

    public function getTodayStatistics()
    {
        // получаем статистику за сегодняшний день
        return $this->getDayStatistics(date('Y-m-d'));
    }

    public function getDayStatistics($date)
    {
        // получаем статистику за определенный день
        return $this->getPeriodStatistics($date, $date);
    }

    public function getCurrentMonthStatistics()
    {
        // получаем статистику за текущий месяц
        return $this->getPeriodStatistics(date('Y-m-01'), date('Y-m-t'));
    }

    public function getLastMonthStatistics()
    {
        // получаем статистику за последний месяц
        $startOfLastMonth = strtotime("first day of last month");
        $endOfLastMonth = strtotime("last day of last month");

        return $this->getPeriodStatistics(date('Y-m-d', $startOfLastMonth), date('Y-m-d', $endOfLastMonth));
    }

    public function getStatisticsForLastNDays($days)
    {
        // получаем статистику за последние N дней
        $dateNDaysAgo = strtotime('-' . $days . ' days');

        return $this->getPeriodStatistics(date('Y-m-d', $dateNDaysAgo), date('Y-m-d'));
    }

    public function getPeriodStatistics($startDate, $endDate)
    {
        // получаем статистику за заданный период от startDate до endDate
        return $this->getMonthStatistics($startDate, $endDate);
    }

    public function getCurrentYearStatistics()
    {
        // Получаем статистику за текущий год
        $startDate = date('Y-01-01'); // начальная дата - первый день текущего года
        $endDate = date('Y-12-31'); // конечная дата - последний день текущего года

        return $this->getPeriodStatistics($startDate, $endDate);
    }

    public function getLastYearStatistics()
    {
        // Получаем статистику за прошлый год
        $startDate = date('Y-01-01', strtotime('-1 year')); // начальная дата - первый день прошлого года
        $endDate = date('Y-12-31', strtotime('-1 year')); // конечная дата - последний день прошлого года

        return $this->getPeriodStatistics($startDate, $endDate);
    }

    public function isBot($user_agent)
    {
        // сверяем user agent посетителя с известным списком bot user agents
        if (!empty($user_agent)) {
            $options = array(
                'YandexBot', 'YandexAccessibilityBot', 'YandexMobileBot','YandexDirectDyn',
                'YandexScreenshotBot', 'YandexImages', 'YandexVideo', 'YandexVideoParser',
                'YandexMedia', 'YandexBlogs', 'YandexFavicons', 'YandexWebmaster',
                'YandexPagechecker', 'YandexImageResizer','YandexAdNet', 'YandexDirect',
                'YaDirectFetcher', 'YandexCalendar', 'YandexSitelinks', 'YandexMetrika',
                'YandexNews', 'YandexNewslinks', 'YandexCatalog', 'YandexAntivirus',
                'YandexMarket', 'YandexVertis', 'YandexForDomain', 'YandexSpravBot',
                'YandexSearchShop', 'YandexMedianaBot', 'YandexOntoDB', 'YandexOntoDBAPI',
                'Googlebot', 'Googlebot-Image', 'Mediapartners-Google', 'AdsBot-Google',
                'Mail.RU_Bot', 'bingbot', 'Accoona', 'ia_archiver', 'Ask Jeeves',
                'OmniExplorer_Bot', 'W3C_Validator', 'WebAlta', 'YahooFeedSeeker', 'Yahoo!',
                'Ezooms', '', 'Tourlentabot', 'MJ12bot', 'AhrefsBot', 'SearchBot', 'SiteStatus',
                'Nigma.ru', 'Baiduspider', 'Statsbot', 'SISTRIX', 'AcoonBot', 'findlinks',
                'proximic', 'OpenindexSpider','statdom.ru', 'Exabot', 'Spider', 'SeznamBot',
                'oBot', 'C-T bot', 'Updownerbot', 'Snoopy', 'heritrix', 'Yeti',
                'DomainVader', 'TelegramBot', 'PaperLiBot'
            );

            foreach($options as $row) {
                if (stripos($user_agent, $row) !== false) {
                    return true;
                }
            }
        }

        return false;
    }
}

Какие недостатки у этого класса? 

Метод trackingVisitors() делает запрос к базе данных каждый раз, когда вызывается. Это может стать проблемой, если у вас много посетителей и вы вызываете данный метод для каждого посетителя.

Как можно оптимизировать 

Эта версия метода trackingVisitors() использует куки пользователей для снижения количества запросов к базе данных и обновления данных только тогда, когда это необходимо (раз в минуту). 

public function trackingVisitors()
{
    // проверяем, является ли посетитель ботом по его user agent
    if(!$this->isBot($this->user_agent)) {
        // ищем посетителя в базе данных по его IP
        $visitor = R::findOne('visitors', 'ip = ?', [$this->ip]);

        // Если есть cookie, увеличиваем его значение
        if (isset($_COOKIE['views'])) {
           // Проверяем, что значение куки является числом. Если нет, устанавливаем его равным 1
           $views = is_numeric($_COOKIE['views']) ? $_COOKIE['views'] + 1 : 1;
           setcookie('views', $views, time() + 60); // обновляем куки на 60 секунд
        } else {
            // Создаем куки, если они не существуют.
            setcookie('views', 1, time() + 60);
        }
         
        // если посетителя нет в базе, создаем нового и устанавливаем для него начальные значения
        if (!$visitor) {
            $visitor = R::dispense('visitors');
            $visitor->ip = $this->ip;
            $visitor->date = $this->date;
            $visitor->user_agent = $this->user_agent;
            $visitor->views = $_COOKIE['views'];
        } else {
            // если посетитель уже есть в базе и прошла минута с момента последнего обновления
            if (time() - strtotime($visitor->updated_at) > 60) {
                // обновляем данные посещения и увеличиваем количество просмотров
                $visitor->date = $this->date;
                $visitor->user_agent = $this->user_agent;
                $visitor->views = $visitor->views + $_COOKIE['views'];
                $visitor->updated_at = date('Y-m-d H:i:s');
            }
        }
        // сохраняем изменения в объекте посетителя в базе данных
        R::store($visitor);
    }
}

эта оптимизация помогает снизить нагрузку на базу данных через использование кук для сохранения количества просмотров, а также обновление данных в базе только тода, когда это необходимо (раз в минуту). 

warning icon

Если ваш сайт имеет большое количество посещений, это может серьезно снизить нагрузку на сервер и увеличить производительность.

Стоит учесть, что куки могут быть легко изменены или удалены пользователями, что в некоторых случаях может привести к некорректным результатам отслеживания.

Примеры использования 

Рассмотрим примеры использования класса Visitors для получения статистики сайта по просмотрам и уникальным посетителям по разным параметрам.

$visitor = new Visitors();
$visitor->trackingVisitors();

Получить статистику за сегодняшний день

Метод getTodayStatistics() класса "Visitors" предназначен для получения статистики посещения веб-сайта за текущий день.

$statistics = $visitor->getTodayStatistics();
print_r($statistics);

Получить статистику за последние N дней

Используя метод getStatisticsForLastNDays() можно просмотреть статистику за прошедшие N дней

$statistics = $visitor->getStatisticsForLastNDays(7);
print_r($statistics);

Получить статистику за определенный день

С помощью метода getDayStatistics(string $date), вы можете легко получить статистику за любой конкретный день:

$statistics = $visitor->getDayStatistics('2024-01-01'); // статистика за 1 января 2024 года
print_r($statistics);

Получить статистику за текущий месяц

Для получения статистики текущего месяца используйте метод getCurrentMonthStatistics():

$visitor = new Visitors();
$statistics = $visitor->getCurrentMonthStatistics(); 
print_r($statistics);

Получить статистику за последний месяц

Чтобы получить статистику за последний месяц, воспользуйтесь методом getLastMonthStatistics():

$statistics = $visitor->getLastMonthStatistics(); 
print_r($statistics);

Получить статистику за текущий год

Метод getCurrentYearStatistics() возвращает статистику за текущий год:

$statistics = $visitor->getCurrentYearStatistics(); 
print_r($statistics);

Получить статистику за прошлый год

Метод getLastYearStatistics() возвращает статистику посещений сайта за прошлый год:

$statistics = $visitor->getLastYearStatistics(); 
print_r($statistics);

Каждый из этих методов возвращает массив, включающий общее количество просмотров и количество уникальных пользователей за соответствующий период.

Оставить комментарий