Laravel 實現文章瀏覽量次數統計

_杭城浪子發表於2018-01-24

由於網上參考的兩篇文章講的不是特別適合自己,在下載和開發的過程中遇到不少的坑,所以就在前輩的基礎上進行整理知識點。
瀏覽量統計的需求:
使用者訪問文章頁面–>取得ip地址和文章id,存入資料庫 再次訪問時根據ip和文章id判斷是否新增記錄,
擴充套件工具:weboAp/Visitor
首先要用composer 載入weboAp/Visitor
在composer.json的require中新增,注意標點符號的遺漏和錯誤,

 {
    "require": {
        "weboap/visitor": "dev-master"
    }
}

2.然後在命令列執行 composer update ,我使用的是 PhpStorm ,所以可以用 alt+F12 調出命令列,輸入即可。
composer update
3.將Service新增到 config/app.php的 providers中,同樣注意標點符號的遺漏和錯誤:
'Weboap\Visitor\VisitorServiceProvider'
4.之後在命令列(phpstorm->ALT+F12)裡執行下面兩個命令:
php artisan vendor:publish
php artisan migrate
5.到 http://dev.maxmind.com/geoip/geoip2/geolite2 下載geoip包(GeoLite2-City.mmdb)將它解壓之後放到以下目錄, geo 資料夾 需要自己建立的storage/geo/
6.上面的步驟之後你將會得到一個表 visitor_registry,這裡我們首先為 visitor_registry 新增一個欄位 art_id 用於 One-To-Many 的關係。
php artisan make:migration add_art_id_to_visitor_registry --table='visitor_registry'
7.在專案的 database 資料夾找到新生成的表格,名字是 日期+add_article_id_to_visitor_registry 在裡面的up方法中寫入

public function up() 
{ 
Schema::table('visitor_registry', function (Blueprint $table) { 
$table->integer('art_id')->unsigned()->index(); 
$table->foreign('art_id')->references('id')->on('article')->onDelete('cascade'); 
}); 
} 

這邊就是我遇到的坑之一,
首先
$table->integer('art_id')->unsigned()->index();
art_id是你文章表格的 id 列名 ,
這邊是在 visitor_registry 新增欄位. 用於新增外來鍵使用的 ,所以這邊改成你需要的屬性,
$table->foreign('art_id')->references('id')->on('article')->onDelete('cascade');
這邊是 visitor_registry 與你的表格新增外來鍵,
這邊也有一個坑,就是死活都無法新增進外來鍵,
大概是這樣↓↓↓好吧,我承認我暴走了= =翻來翻去找不到答案,
然後我就去睡了一覺,起來以後再翻翻stackoverflow,然後就解決了。
可能是你程式碼打錯了,檢查一下。
可能是主表的鍵沒有設定無符號,這是國外友人提的,並被那個問主採納了,那你就看看兩個表的外來鍵屬性是否一致。
最後這是我遇到的原因,大概是咸豐年前(其實就一個星期前),我開發部落格系統的時候,把表格的引擎都改成了MyISAM ,而透過 migrate 生成的表格是預設InnoDB ,所以,它!就!添!加!不!成!功!
如果還不能解決,那我也沒辦法幫你了,科學上網,翻牆後出去大型基佬聚會會所stackoverflow看看。
8.執行
php artisan migrate
9.接下來新增模型,
php artisan make:model VisitorRegistry
10.再接下來是在模型裡面新增

protected $table = 'visitor_registry';
protected $fillable = ['clicks'];
public function articles()
{
    return $this->belongsTo('App\Article');
}

11.再接下來就在你要計算瀏覽數的那個模型,也就是文章展示的模型中新增一對多的關係

public function visitors()
   {
       return $this->hasMany('App\VisitorRegistry');
   }

12.我們在第7步中給原先的表格新增了一個屬性,所以我們需要修改原來擴充套件包裡面的log()方法
在方法中新增引數
public function log($art_id){}
在修改第二個If語句

if( $this->has( $ip ) && $this->hasArticle($art_id,$ip) )
        {
            //ip already exist in db.
            $visitor = VisitorRegistry::where('ip','=',$ip)->where('art_id','=',$art_id)->first();
            $visitor->update(['clicks'=>$visitor->clicks + 1]);
            return true;
        }

上面我們自己新增了一個 hasArticle($article_id,$ip),我們可以直接將這個方法寫在 Visitor.php 中:

public function hasArticle($id,$ip)
    {
        return count(VisitorRegistry::where('art_id','=',$id)->where('ip','=',$ip)->get()) > 0;
    }

最後我們還要修改log()中的插入資料的陣列資料$data

$data = array(
                    'ip'        => $ip,
                    'country'   => $country,
                    'clicks'    => 1,
                    'art_id' => $art_id,
                    'updated_at'    => c::now(),
                    'created_at'    => c::now()
                    );

完整的方法是:

 public function log($art_id)
    {
        $ip = $this->ip->get();
        if (!$this->ip->isValid($ip)) {
            return;
        }
        if ($this->has( $ip ) && $this->hasArticle($art_id,$ip) ) {
            //ip already exist in db.
            $visitor = VisitorRegistry::where('ip','=',$ip)->where('art_id','=',$art_id)->first();
            $visitor->update(['clicks'=>$visitor->clicks + 1]);
            return true;
        } else {
            $geo = $this->geo->locate($ip);
            $country = array_key_exists('country_code', $geo) ? $geo['country_code'] : null;
            //ip doesnt exist  in db
            $data = [
                'ip'        => $ip,
                'country'   => $country,
                'clicks'    => 1,
                'art_id' => $art_id,
                'updated_at'    => c::now(),
                'created_at'    => c::now()
            ];
            $this->storage->create($data);
        }
        // Clear the database cache
        $this->cache->destroy('weboap.visitor');
    }

好了,super 完美。

本作品採用《CC 協議》,轉載必須註明作者和本文連結
刻意練習,每日精進

相關文章