Skip to content

统计服务

基于 app/System/Service/Stats.phpapp/System/Service/Visitor.php 的统计服务,提供数据统计计算和访问统计功能。

🚀 快速开始

基础使用

php
use App\System\Service\Stats;
use App\System\Service\Visitor;

// 计算环比增长率
$rate = Stats::calculateRate($currentValue, $previousValue);

// 记录访问统计
Visitor::increment($request, 'article', $articleId, 'web', '/article/123');

📋 主要功能

1. 增长率计算 (Stats)

php
use App\System\Service\Stats;

// 计算环比增长率
$thisMonth = 1200;
$lastMonth = 1000;
$growthRate = Stats::calculateRate($thisMonth, $lastMonth); // 20.0

// 处理零值情况
$rate1 = Stats::calculateRate(100, 0);   // 100.0 (从0增长到100,增长率100%)
$rate2 = Stats::calculateRate(0, 100);   // -100.0 (从100降到0,下降率100%)
$rate3 = Stats::calculateRate(0, 0);     // 0.0 (都为0,无变化)

2. 访问统计 (Visitor)

php
use App\System\Service\Visitor;

// 记录页面访问
Visitor::increment($request, 'page', null, 'web', '/home');

// 记录文章访问
Visitor::increment($request, 'article', 123, 'web', '/article/123');

// 记录产品访问
Visitor::increment($request, 'product', 456, 'api', '/api/product/456');

// 参数说明:
// $request: 请求对象(用于获取IP、User-Agent等)
// $type: 统计类型(如 'page', 'article', 'product')
// $id: 关联ID(可选,用于关联具体内容)
// $driver: 驱动类型(如 'web', 'api', 'mobile')
// $path: 访问路径(可选,记录具体访问路径)

🔧 实际应用示例

1. 数据分析服务

php
<?php

namespace App\System\Service;

use App\System\Service\Stats;

class AnalyticsService
{
    /**
     * 获取业务增长分析
     */
    public static function getGrowthAnalysis(string $period = 'month'): array
    {
        // 获取当前周期和上个周期的数据
        $currentData = self::getCurrentPeriodData($period);
        $previousData = self::getPreviousPeriodData($period);

        $analysis = [];

        foreach ($currentData as $metric => $currentValue) {
            $previousValue = $previousData[$metric] ?? 0;
            
            $analysis[$metric] = [
                'current' => $currentValue,
                'previous' => $previousValue,
                'growth_rate' => Stats::calculateRate($currentValue, $previousValue),
                'growth_value' => $currentValue - $previousValue,
                'trend' => self::getTrend($currentValue, $previousValue)
            ];
        }

        return [
            'period' => $period,
            'analysis' => $analysis,
            'generated_at' => date('Y-m-d H:i:s')
        ];
    }

    /**
     * 生成统计报告
     */
    public static function generateReport(array $metrics, string $period = 'month'): array
    {
        $report = [
            'period' => $period,
            'metrics' => [],
            'summary' => [],
            'generated_at' => date('Y-m-d H:i:s')
        ];

        $totalGrowthRate = 0;
        $positiveMetrics = 0;

        foreach ($metrics as $metric => $data) {
            $currentValue = $data['current'];
            $previousValue = $data['previous'];
            $growthRate = Stats::calculateRate($currentValue, $previousValue);

            $report['metrics'][$metric] = [
                'name' => $data['name'] ?? $metric,
                'current' => $currentValue,
                'previous' => $previousValue,
                'growth_rate' => $growthRate,
                'growth_value' => $currentValue - $previousValue,
                'trend' => self::getTrend($currentValue, $previousValue),
                'status' => $growthRate >= 0 ? 'positive' : 'negative'
            ];

            $totalGrowthRate += $growthRate;
            if ($growthRate > 0) {
                $positiveMetrics++;
            }
        }

        // 生成摘要
        $report['summary'] = [
            'total_metrics' => count($metrics),
            'positive_metrics' => $positiveMetrics,
            'negative_metrics' => count($metrics) - $positiveMetrics,
            'average_growth_rate' => count($metrics) > 0 ? $totalGrowthRate / count($metrics) : 0,
            'overall_trend' => $totalGrowthRate >= 0 ? 'positive' : 'negative'
        ];

        return $report;
    }

    /**
     * 获取趋势描述
     */
    private static function getTrend(float $current, float $previous): string
    {
        if ($current > $previous) {
            return 'up';
        } elseif ($current < $previous) {
            return 'down';
        } else {
            return 'stable';
        }
    }

    /**
     * 获取当前周期数据
     */
    private static function getCurrentPeriodData(string $period): array
    {
        // 实际实现中从数据库获取数据
        switch ($period) {
            case 'day':
                return self::getDailyData();
            case 'week':
                return self::getWeeklyData();
            case 'month':
                return self::getMonthlyData();
            case 'year':
                return self::getYearlyData();
            default:
                return self::getMonthlyData();
        }
    }

    /**
     * 获取上个周期数据
     */
    private static function getPreviousPeriodData(string $period): array
    {
        // 实际实现中从数据库获取数据
        switch ($period) {
            case 'day':
                return self::getPreviousDailyData();
            case 'week':
                return self::getPreviousWeeklyData();
            case 'month':
                return self::getPreviousMonthlyData();
            case 'year':
                return self::getPreviousYearlyData();
            default:
                return self::getPreviousMonthlyData();
        }
    }

    // 示例数据获取方法
    private static function getMonthlyData(): array
    {
        return [
            'users' => 1200,
            'orders' => 450,
            'revenue' => 25000,
            'page_views' => 15000
        ];
    }

    private static function getPreviousMonthlyData(): array
    {
        return [
            'users' => 1000,
            'orders' => 380,
            'revenue' => 22000,
            'page_views' => 12000
        ];
    }
}

2. 访问统计服务

php
<?php

namespace App\System\Service;

use App\System\Service\Visitor;

class VisitorStatsService
{
    /**
     * 记录内容访问
     */
    public static function recordContentView($request, string $contentType, int $contentId): void
    {
        $path = $request->getUri()->getPath();
        Visitor::increment($request, $contentType, $contentId, 'web', $path);
    }

    /**
     * 记录 API 访问
     */
    public static function recordApiAccess($request, string $endpoint): void
    {
        Visitor::increment($request, 'api', null, 'api', $endpoint);
    }

    /**
     * 获取访问统计
     */
    public static function getVisitorStats(string $type, int $id = null, string $period = 'month'): array
    {
        // 实际实现中需要查询 log_visit 相关表
        // 这里提供示例数据结构
        
        return [
            'type' => $type,
            'id' => $id,
            'period' => $period,
            'stats' => [
                'total_views' => 1250,
                'unique_visitors' => 890,
                'today_views' => 45,
                'today_unique' => 32,
                'avg_daily_views' => 42,
                'peak_day' => '2024-01-15',
                'peak_day_views' => 78
            ],
            'trend' => [
                'views_growth_rate' => 15.5,
                'visitors_growth_rate' => 12.3
            ]
        ];
    }

    /**
     * 获取热门内容
     */
    public static function getPopularContent(string $type, int $limit = 10, string $period = 'month'): array
    {
        // 实际实现中查询数据库
        return [
            'type' => $type,
            'period' => $period,
            'limit' => $limit,
            'items' => [
                [
                    'id' => 123,
                    'title' => '热门文章标题',
                    'views' => 1500,
                    'unique_visitors' => 1200,
                    'growth_rate' => 25.5
                ],
                // ... 更多项目
            ]
        ];
    }

    /**
     * 获取访问来源统计
     */
    public static function getTrafficSources(string $period = 'month'): array
    {
        return [
            'period' => $period,
            'sources' => [
                'direct' => [
                    'visits' => 5000,
                    'percentage' => 45.5,
                    'growth_rate' => 10.2
                ],
                'search' => [
                    'visits' => 3500,
                    'percentage' => 31.8,
                    'growth_rate' => 15.7
                ],
                'social' => [
                    'visits' => 1500,
                    'percentage' => 13.6,
                    'growth_rate' => -5.3
                ],
                'referral' => [
                    'visits' => 1000,
                    'percentage' => 9.1,
                    'growth_rate' => 8.9
                ]
            ]
        ];
    }
}

3. 实时统计服务

php
<?php

namespace App\System\Service;

use App\System\Service\Stats;

class RealTimeStatsService
{
    /**
     * 获取实时统计数据
     */
    public static function getRealTimeStats(): array
    {
        return [
            'online_users' => self::getOnlineUsers(),
            'today_stats' => self::getTodayStats(),
            'recent_activities' => self::getRecentActivities(),
            'system_status' => self::getSystemStatus()
        ];
    }

    /**
     * 获取在线用户数
     */
    private static function getOnlineUsers(): array
    {
        // 实际实现中查询活跃会话
        $current = 156;
        $previous = 142;
        
        return [
            'count' => $current,
            'growth_rate' => Stats::calculateRate($current, $previous),
            'peak_today' => 189,
            'avg_today' => 145
        ];
    }

    /**
     * 获取今日统计
     */
    private static function getTodayStats(): array
    {
        $todayData = [
            'page_views' => 2450,
            'unique_visitors' => 1890,
            'new_users' => 45,
            'orders' => 23
        ];

        $yesterdayData = [
            'page_views' => 2200,
            'unique_visitors' => 1750,
            'new_users' => 38,
            'orders' => 19
        ];

        $stats = [];
        foreach ($todayData as $key => $value) {
            $previousValue = $yesterdayData[$key] ?? 0;
            $stats[$key] = [
                'value' => $value,
                'growth_rate' => Stats::calculateRate($value, $previousValue),
                'trend' => $value > $previousValue ? 'up' : ($value < $previousValue ? 'down' : 'stable')
            ];
        }

        return $stats;
    }

    /**
     * 获取最近活动
     */
    private static function getRecentActivities(): array
    {
        return [
            [
                'type' => 'user_register',
                'message' => '新用户注册',
                'count' => 3,
                'time' => '5分钟前'
            ],
            [
                'type' => 'order_created',
                'message' => '新订单创建',
                'count' => 2,
                'time' => '8分钟前'
            ],
            [
                'type' => 'article_published',
                'message' => '文章发布',
                'count' => 1,
                'time' => '15分钟前'
            ]
        ];
    }

    /**
     * 获取系统状态
     */
    private static function getSystemStatus(): array
    {
        return [
            'cpu_usage' => 45.2,
            'memory_usage' => 67.8,
            'disk_usage' => 34.5,
            'response_time' => 120, // 毫秒
            'error_rate' => 0.02,   // 2%
            'uptime' => '15天 8小时 32分钟'
        ];
    }
}

💡 最佳实践

1. 统计数据缓存

php
// ✅ 缓存统计结果
class CachedStatsService
{
    private static array $cache = [];
    private static int $cacheTtl = 300; // 5分钟

    public static function getCachedStats(string $key, callable $calculator): array
    {
        $cacheKey = "stats_{$key}";
        
        if (isset(self::$cache[$cacheKey])) {
            $cached = self::$cache[$cacheKey];
            if (time() - $cached['time'] < self::$cacheTtl) {
                return $cached['data'];
            }
        }

        $data = $calculator();
        self::$cache[$cacheKey] = [
            'data' => $data,
            'time' => time()
        ];

        return $data;
    }
}

2. 异步统计处理

php
// ✅ 异步处理大量统计数据
use Core\App;

class AsyncStatsService
{
    public static function processStatsAsync(array $data): void
    {
        // 将统计处理放入队列
        App::queue()->add(
            'App\Jobs\StatsProcessJob',
            'process',
            [$data]
        )->send();
    }
}

3. 统计数据验证

php
// ✅ 验证统计数据的有效性
public function validateStatsData(array $data): bool
{
    foreach ($data as $key => $value) {
        if (!is_numeric($value) || $value < 0) {
            return false;
        }
    }
    return true;
}

4. 错误处理

php
// ✅ 统计服务的错误处理
public function safeCalculateRate(float $current, float $previous): float
{
    try {
        return Stats::calculateRate($current, $previous);
    } catch (\Exception $e) {
        logger()->warning('统计计算失败', [
            'current' => $current,
            'previous' => $previous,
            'error' => $e->getMessage()
        ]);
        return 0.0;
    }
}

🎉 总结

统计服务的特点:

  • 📊 功能完整:涵盖增长率计算和访问统计
  • ⚡ 高性能:支持缓存和异步处理
  • 🔍 数据准确:完善的数据验证和错误处理
  • 📈 实时统计:支持实时数据监控
  • 🛡️ 安全可靠:完善的异常处理机制

通过合理使用统计服务,可以构建强大的数据分析和监控系统!