Mar*_*ann -1 php mysql laravel laravel-4
我正计划用PHP编写一个用于博客的视图计数.计数器的目的是指示博客文章的阅读频率,例如StackOverflow在问题页面上显示"浏览n次".
首先,我想将计数器数据存储在文件中,但通过研究,我改变了主意,将MySQL与几个InnoDB表一起使用,因为这些表的执行速度比硬盘查找速度快,从长远来看也不那么费力,而且本身也提供了有用的功能.
我坚持的问题是如何只为每个用户计算一次?
限制IP不是一种解决方案,因为动态IP和网络通常只有一个IP与所有连接的设备(例如学校,办公室,公共接入点)共享连接.
编辑:
受到fideloper的回答的启发,我正在研究基于会话的解决方案.
我已经在会话中使用单独的数据库表,所以我会按照建议将其合并到解决方案中.
这是我到目前为止(使用Laravel 4和Eloquent ORM):
SQL表设置:
--
-- Sessions Table
--
CREATE TABLE sessions (
id VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
payload TEXT NOT NULL COLLATE 'utf8_unicode_ci',
last_activity INT(11) NOT NULL,
UNIQUE INDEX sessions_id_unique (id)
) COLLATE='utf8_unicode_ci' ENGINE=InnoDB;
--
-- Views Table
--
CREATE TABLE post_views (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
post_id INT(11) UNSIGNED NOT NULL,
sess_id VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
viewed_at TIMESTAMP NULL DEFAULT NULL,
PRIMARY KEY (id)
) COLLATE='utf8_unicode_ci' ENGINE=InnoDB;
--
-- Posts Table
--
CREATE TABLE posts (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
user_id INT(11) UNSIGNED NOT NULL,
title VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
excerpt TEXT NOT NULL COLLATE 'utf8_unicode_ci',
slug VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
content LONGTEXT NOT NULL COLLATE 'utf8_unicode_ci',
...
views INT(10) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (id)
) COLLATE='utf8_unicode_ci' ENGINE=InnoDB;
Run Code Online (Sandbox Code Playgroud)
PHP视图计数器类:
<?php namespace Services\Posts;
/**
* Blog Post Views Counter
*
* Using Laravel 4 with Eloquent ORM
*/
class ViewsCounter {
public $post_id;
/**
* Sets the post id
*
* @param int $id
* @return void
*/
public function setPostID($id)
{
$this->post_id = $id;
}
/**
* Handles the view count
*
* @return bool True or false on failure
*/
public function countView()
{
// Get the post data from the db
try
{
$post = \Post::findOrFail($this->post_id);
}
catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e)
{
return false;
}
// Get the current session id
$sess_id = session_id();
// Check if this view was already counted by
// looking up the session id in the views table
$post_views = \PostViews::where('sess_id', '=', $sess_id)
->where('post_id', '=', $this->post_id)
->remember(10)
->first();
// The sess_id was not found so count the view
if (empty($post_views))
{
$post_views->post_id = $this->post_id;
$post_views->sess_id = $sess_id;
$post_views->viewed_at = date('Y-m-d H:i:s');
$post_views->save();
// A cronjob is run every 24 hours to count the views per
// post and update the count values in the posts table.
// The post_views table will be truncated when done.
}
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
建议表示赞赏.
每个用户计算+1个观看次数的问题很有意思,因为您需要考虑会话.
您确实需要为每个会话ID执行+1次计数(因为它会为每个用户重新生成,但更有可能在每次访问时为每个用户提供+1次查看次数...具体取决于您的代码).请注意,这意味着在新会话中再次访问该网站的用户将再次计算视图计数.
如果您需要跟踪会话ID,可能需要执行以下操作:
您也可以随时缩短24小时.您可能(将)最终在视图计数更新时计算一些额外的视图计数,并且要比较的会话ID被删除.
希望能为你激发一些想法.
| 归档时间: |
|
| 查看次数: |
3010 次 |
| 最近记录: |