【问题标题】:Using middleware in laravel to determine page visits在 laravel 中使用中间件判断页面访问量
【发布时间】:2020-07-01 22:57:21
【问题描述】:
Public function handle($request, Closure $next)
{
    $count = 0;
    $time = now();
    $visitor = "Someone";

    if (request("visitor") == "Someone" && $count == 0) {
        $count++;
        \Mail::raw('You have a new page visit at ' . $time ' ' . $count . '', function ($note) {
            $note->to('manager@mail.com');
        });

        return $next($request);
    } else {
        return abort (404);
    }

这段代码只是一个简单的中间件,用于检查 laravel 中的页面访问。一切正常,我正在通过日志收到电子邮件。但是,每个页面点击的计数仅为 1。不会增加到2、3……

我真的需要帮助才能计算页面点击量,无论访问者是谁或访问什么内容,甚至无论 IP 是什么。另外,我如何将计数获取到视图并将其保存在数据库中。我真的需要帮助,因为我还是个学习者。请帮忙!

【问题讨论】:

  • 您的计数永远不会超过 1,因为您每次调用中间件时都会重新声明它。您尝试做的事情可能最好由分析服务完成。

标签: laravel middleware


【解决方案1】:

我曾经做过类似的事情,但是对于用户遇到的系统问题。由于您要测量流量(使用数据库),因此场景有点相似。假设您有一个名为 traffic 的表,因此有关流量的逻辑将像您一样放在中间件的句柄函数中,但像这样测量流量:

public function handle($request, Closure $next)
{
    $time = now(); // @Todo: check timezone in the config/app.php

    $visitor = $request->ip();
    $traffic = Traffic::where('visitor', $visitor)->first();

    if ($traffic) {
        // Resident visitor
        $traffic->visits++;
        $traffic->update();

    } else {
        // New visitor
        $traffic = new Traffic(['visitor' => $visitor]);
        $traffic->save();

        $totalTraffic = Traffic::all()->sum('visits');
        $totalVisitors = Traffic::all()->count();

        // Email notification
        \Mail::raw("There is a new visitor at {$time} from ip {$visitor}.\nIn total there are {$totalVisitors} visitors, and over all you have {$totalTraffic} visits.", function ($note) {
            $note->to('manager@mail.com');
        });
    }

    return $next($request);
}

请记住,您可以通过在模型中实现引导功能将流量逻辑移入流量模型来改进此解决方案,这样看起来会更简洁。更多信息https://laravel.com/docs/7.x/eloquent#observers

抱歉来晚了,希望对你有帮助...

解决方案 2: 您还可以创建迁移或在数据库中运行以下语句,将访问的默认列设置为 1,因为每次创建新列时它都不会更改。

ALTER TABLE 流量 ALTER 访问 SET DEFAULT 1;

交通模型:

class Traffic extends Model
{
    protected $fillable = ['visitor' , 'visits'];

    protected static function boot()
    {
        parent::boot();

        static::saving(function ($traffic) {
            if ($traffic->visits) {
                $traffic->visits++;
            }
        });
    }
}

交通中间件:

public function handle($request, Closure $next)
{
    $time = now();

    $visitor = $request->ip();
    $traffic = Traffic::firstOrCreate(['visitor' => $visitor]);
    $traffic->save();

    //Email notification
    $totalTraffic = Traffic::all()->sum('visits');
    $totalVisitors = Traffic::all()->count();

    \Mail::raw("New visit at {$time} from {$visitor}. You have over all {$totalTraffic} visits from {$totalVisitors} visitors.", function ($note) {
        $note->to('manager@mail.com');
    });

    return $next($request);
}

【讨论】:

  • 感谢@hmg 提供更多帮助。所以我的流量模型将有表格列,如:ID、访问、IP 地址和时间戳,对吗?如果我把逻辑移到Traffic模型中,中间件如何检测路由访问的页面?对于这些问题,我很抱歉,我只是想确定这一切是如何运作的。提前致谢。
  • 当然@cd4success。您的模型可以像那样简单地开始,也可以随着时间的推移而增长,这取决于您的需求,但会给您一些灵活性。为了将中间件附加到您的路由,您需要确保中间件已加载到您的路由中间件数组中的 app/Http/Kernel.php 中,例如 ...,'traffic' => \App\Http\Middleware\TrafficMiddleware::class ] 对于中间件在您的路线中使用 web.php 路线文件:Route::group(['middleware' => 'traffic'], function () { // All desired tracking routes in here... });
  • 非常感谢@hmg。我也会利用这个。但请我有最后一个问题。我有三个页面(主页、帖子和关于)。访问该站点的任何人都可以查看这三个页面。但是,有些页面包含页眉和页脚之间的内容,只有登录用户才能访问。我发现很难使用 auth 中间件来隐藏内容。不确定如何使用 at-guest、at-auth 等指令。请非常感谢您的帮助。提前致谢
  • 没问题@cd4success,我添加了第二个解决方案,因此您可以看到从流量中间件调用模型逻辑时的样子。不确定到目前为止您为 auth 中间件尝试了什么,也许这个链接可以帮助laracasts.com/discuss/channels/laravel/… ...
【解决方案2】:

首先,如果你每次都重新声明$count,它永远不会增加。

其次,您在发送邮件之前检查$count是否等于0,所以即使它确实增加了,您下次也不会发送邮件。

保持计数值的一种方法是使用缓存。

public function handle($request, Closure $next)
{
    // retrieve cached value for 'page_visits'. If it doesn't exist, return 0 instead
    $count = cache('page_visits', 1);
    $visitor = request()->ip();
    $time = now();

    \Mail::raw("You have a new page visit at {$time->isoFormat('LLLL')} from {$visitor}. Total: {$count}", function ($note) {
        $note->to('manager@mail.com');
    });

    cache()->put('page_visits', ++$count);

    return $next($request);
}

【讨论】:

  • 非常感谢@IGP。您的解决方案有效,但它没有保持价值。它一直在记录 1...1...1...没有增加到 2 和 3 和 4....... 请问我该如何解决这个问题?以及如何将计数器发送到视图?
  • 我刚刚对此进行了测试,它适用于我。您也可以使用 cache() 帮助器检索视图中的缓存值。例如:<h1>Page visits: {{ cache('page_visits', 0) }}</h1>
  • 我检查了代码的每一个细节,没有遗漏任何东西,但它仍然没有增加。但是邮件后面的“cache()put->”根本没有显示任何值。我不得不将它移动到电子邮件的顶部,然后它显示为 1,而不是任何增量。请检查代码,因为我已经彻底检查过了。当您刷新或重新访问您附加中间件的页面时,您是否获得了增量?请告诉我。
  • 请发自内心的原谅我。我刚刚从最高层看到了我的错误。 cache(‘page_visits,1’); ..... cache(‘page_visits’, 1); .....。它就像一个魅力!非常感谢。日志和页面中的计数都会增加。你刚刚救了一条命……
  • 最后一件事@IGP。请问有没有办法可以使用 Carbon 来确定几分钟或几小时或几天或几周前的访问?
猜你喜欢
  • 1970-01-01
  • 2013-04-09
  • 2016-12-15
  • 2015-10-15
  • 1970-01-01
  • 2021-11-13
  • 1970-01-01
  • 2011-06-27
  • 2017-08-06
相关资源
最近更新 更多