php 新闻中点击次数,Laravel 运用事件Event完成新闻访问量统计

需求描述:用户浏览文章记录该篇文章的访问量。

准  备:在文章表中加一个字段‘news_clicks’,用来存放访问量。

完成效果:同一个用户session有效时间内浏览文章记录一次访问量。

这个是关于文章的浏览数的实现,当用户查看文章的时候文章的浏览数会增加1,用户查看文章就是一个事件,有了事件,就需要一个事件监听器,对监听的事件发生后执行相应的操作(文章浏览数加1),其实这种监听机制在 Laravel 中是通过观察者模式实现的.

1、注册事件以及监听器

首先我们需要在 app/Providers/目录下的EventServiceProvider.php中注册事件监听器映射关系,如下:

protected $listen = [

/*'App\Events\Event' => [

'App\Listeners\EventListener',

],*/

'App\Events\NewsView' => [

'App\Listeners\NewsViewListener',

],

];

2、然后项目根目录下执行如下命令

php artisan event:generate

该命令完成后,会分别自动在 app/Events和app/Listensers目录下生成 NewsView.php和NewsView

3、定义事件

namespace App\Events;

use App\http\model\index_news;

use Illuminate\Broadcasting\Channel;

use Illuminate\Broadcasting\InteractsWithSockets;

use Illuminate\Broadcasting\PresenceChannel;

use Illuminate\Broadcasting\PrivateChannel;

use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

use Illuminate\Foundation\Events\Dispatchable;

use Illuminate\Queue\SerializesModels;

class NewsView

{

use Dispatchable, InteractsWithSockets, SerializesModels;

/**

* Create a new event instance.

*

* @return void

*/

public function __construct(index_news $news)

{

//注入了一个 index_news实例

$this->news = $news;

}

/**

* Get the channels the event should broadcast on.

*

* @return \Illuminate\Broadcasting\Channel|array

*/

public function broadcastOn()

{

/*return new PrivateChannel('channel-name');*/

return [];

}

}

其实看到这些你会发现该事件类只是注入了一个News实例罢了,并没有包含多余的逻辑。

4、定义监听器

事件监听器在handle方法中接收事件实例,event:generate命令将会自动在handle方法中导入合适的事件类和类型提示事件。在handle方法内,你可以执行任何需要的逻辑以响应事件,我们的代码实现如下:

namespace App\Listeners;

use App\Events\NewsView;

use Illuminate\Contracts\Queue\ShouldQueue;

use Illuminate\Queue\InteractsWithQueue;

use Illuminate\Session\Store;

class NewsViewListener

{

protected $session;

/**

* Create the event listener.

*

* @return void

*/

public function __construct(Store $session)

{

//

$this->session = $session;

}

/**

* Handle the event.

*

* @param NewsView $event

* @return void

*/

public function handle(NewsView $event)

{

//

$news = $event->news;

//先进行判断是否已经查看过

if(!$this->hasViewedNews($news)){

//保存到数据库

$news->news_clicks = $news->news_clicks + 1;

$news->save();

//看过之后将保存到Session

$this->storeViewedNews($news);

}

}

/**

* 判断当前文章在session中是否已经存在浏览记录

* @param $news

* @return bool

*/

protected function hasViewedNews($news){

return array_key_exists($news->id,$this->getViewsNews());

}

/**

* 从session中获取浏览记录

* @return mixed

*/

protected function getViewsNews(){

return $this->session->get('viewed_news',[]);

}

/**

* 存储浏览记录到session

* @param $news

*/

protected function storeViewedNews($news){

$key = 'viewed_news.'.$news->id;

$this->session->put($key,time());

}

}

注释中也说明了一些逻辑

5、触发事件

事件和事件监听完成后,我们要做的就是实现整个监听,即触发用户打开文章事件,触发事件只需要断言特定事件被分发,而不需要真正地触发监听器,如下:

class DetailController extends BaseController

{

//资讯详情

public function newsDetail($id){

$news = index_news::find($id);

$menuId=$news->menu_id;

switch($menuId){

case(4):$title='院内新闻';break;

case(7):$title='通知公告';break;

case(6):$title='学术动态';break;

case(32):$title='健康知识';break;

case(34):$title='人才招聘';break;

}

/*触发浏览记录事件*/

\event(new NewsView($news));

return view('home.news.detail',compact('news','title'));

}

现在打开页面发现数据库中的‘news_clicks’已经正常加1了,这样整个就完成了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值