我想制作一个 PHP if条件代码,用于检查用户阅读的文章中的最后10篇文章或10分钟是否已经过去。
E.g。
用户打开 id = 235 的页面(此ID值位于url localhost / article / 235中)
此 ID 值将保存在当前时间戳的会话中,并且可能他的IP地址
然后他读了另一篇文章,同样会发生。
我需要记住点击的内容再过10次点击,然后重置仅针对第一行。例如。在第10次点击后,id和时间戳将不会成为第11行,但会替换列表中的第1行。
CodeIgniter中的php条件将检查这些值,并将更新文章表和列计数器中的文章点击计数器值,如下所示:
$this->db->where('id', $id);
$this->db->set('counter', 'counter+1', FALSE);
$this->db->update('articles');
但在调用此代码之前,我需要从会话中进行此检查吗?
怎么做?
我认为存储,例如会话中有10个条目,每个用户的时间戳就足够了。
只是不要在会话中保存同一页两次。
条件将检查当前时间戳与保存的时间戳,如果它超过例如10分钟或者用户已经阅读/点击了另外10篇文章,它将允许更新计数器php代码。
我不需要这种防弹。只是使用浏览器的刷新按钮禁用增量。
所以,如果他想增加柜台,他需要等十分钟或阅读另外10篇文章;)
答案 0 :(得分:4)
你一定要参加Sessions。它可以节省您的带宽消耗,并且更容易处理。当然,除非您需要客户端的数据,根据您的解释,我认为您没有。假设您参加了会议,您所要做的就是使用您拥有的数据存储数组。以下代码应该这样做:
$aClicks = $this->session
->userdata('article_clicks');
// Initialize the array, if it's not already initialized
if ($aClicks == false) {
$aClicks = array();
}
// Now, we clean our array for the articles that have been clicked longer than
// 10 minutes ago.
$aClicks = array_filter(
$aClicks,
function($click) {
return (time() - $click['time']) < 600; // Less than 10 minutes elapsed
}
);
// We check if the article clicked is already in the list
$found = false;
foreach ($aClicks as $click) {
if ($click['article'] === $id) { // Assuming $id holds the article id
$found = true;
break;
}
}
// If it's not, we add it
if (!$found) {
$aClicks[] = array(
'article' => $id, // Assuming $id holds the article id
'time' => time()
);
}
// Store the clicks back to the session
$this->session
->set_userdata('article_clicks', $aClicks);
// If we meet all conditions
if (count($aClicks) < 10) {
// Do something
}
答案 1 :(得分:2)
我认为$ clicks是一个包含多达十篇文章的数组。 id用作键,时间戳用作值。 $ id是新文章的ID。
$clicks = $this->session->userdata('article_clicks');
//default value
$clicks = ($clicks)? $clicks : array();
//could be loaded from config
$maxItemCount = 10;
$timwToLive= 600;
//helpers
$time = time();
$deadline = $time - $timeToLive;
//add if not in list
if(! isset($clicks[$id]) ){
$clicks[$id] = $time;
}
//remove old values
$clicks = array_filter($clicks, function($value){ $value >= $deadline;});
//sort newest to oldest
arsort($clicks);
//limit items, oldest will be removed first because we sorted the array
$clicks = array_slice($clicks, 0, $maxItemCount);
//save to session
$this->session->>set_userdata('article_clicks',$clicks)
用法:
//print how mch time has passed since the last visit
if(isset($clicks[$id]){
echo "visited ".($time-$clicks[$id]). "seconds ago." ;
} else {
echo "first visit";
}
编辑:你必须使用arsort而不是rsort,否则密钥会丢失,抱歉
答案 2 :(得分:1)
根据Raphael_代码和您的问题,您可以尝试:
<?php
$aClicks = $this->session
->userdata('article_clicks');
$nextId = $this->session->userdata('nextId');
// Initialize the array, if it's not already initialized
if ($aClicks == false) {
$aClicks = array();
$nextId = 0;
}
// Now, we clean our array for the articles that have been clicked longer than
// 10 minutes ago.
$aClicks = array_filter($aClicks, function($click) {
return (time() - $click['time']) < 600; // Less than 10 minutes elapsed
}
);
// We check if the article clicked is already in the list
$found = false;
foreach ($aClicks as $click) {
if ($click['article'] === $id) { // Assuming $id holds the article id
$found = true;
break;
}
}
// If it's not, we add it
if (!$found) {
$aClicks[$nextId] = array(
'article' => $id, // Assuming $id holds the article id
'time' => time()
);
$nextId++;
$this->session->set_userdata('nextId', $nextId);
}
$this->session->set_userdata('article_clicks', $aClicks);
if (count($aClicks) > 10 && $nextId > 9) {
$this->session->set_userdata('nextId', 0);
echo "OK!";
}
?>
答案 3 :(得分:1)
我希望我能正确理解你的需要。
用法:
$this->load->library('click');
$this->click->add($id, time());
类API非常简单,代码已注释。您还可以检查项expired()
是否exists()
,get()
项目是否可以节省时间。
请记住:
$ttl
)会话中只保存了10个项目(参见$max_entries
)
class Click
{
/**
* CI instance
* @var object
*/
private $CI;
/**
* Click data holder
* @var array
*/
protected $clicks = array();
/**
* Time until an entry will expire
* @var int
*/
protected $ttl = 600;
/**
* How much entries do we store ?
* @var int
*/
protected $max_entries = 10;
// -------------------------------------------------------------------------
public function __construct()
{
$this->CI =& get_instance();
if (!class_exists('CI_Session')) {
$this->CI->load->library('session');
}
// load existing data from user's session
$this->fetch();
}
// -------------------------------------------------------------------------
/**
* Add a new page
*
* @access public
* @param int $id Page ID
* @param int $time Added time (optional)
* @return bool
*/
public function add($id, $time = null)
{
// If page ID does not exist and limit has been reached, stop here
if (!$this->exist($id) AND (count($this->clicks) == $this->max_entries)) {
return false;
}
$time = !is_null($time) ? $time : time();
if ($this->expired($id)) {
$this->clicks[$id] = $time;
return true;
}
return false;
}
/**
* Get specified page ID data
*
* @access public
* @param int $id Page ID
* @return int|bool Added time or `false` on error
*/
public function get($id)
{
return ($this->exist($id)) ? $this->clicks[$id] : false;
}
/**
* Check if specified page ID exists
*
* @access public
* @param int $id Page ID
* @return bool
*/
public function exist($id)
{
return isset($this->clicks[$id]);
}
/**
* Check if specified page ID expired
*
* @access public
* @param int $id Page ID
* @return bool
*/
public function expired($id)
{
// id does not exist, return `true` so it can added
if (!$this->exist($id)) {
return true;
}
return ((time() - $this->clicks[$id]) >= $this->ttl) ? true : false;
}
/**
* Store current clicks data in session
*
* @access public
* @return object Click
*/
public function save()
{
$this->CI->session->set_userdata('article_clicks', serialize($this->clicks));
return $this;
}
/**
* Load data from user's session
*
* @access public
* @return object Click
*/
public function fetch()
{
if ($data = $this->CI->session->userdata('article_clicks')) {
$this->clicks = unserialize($data);
}
return $this;
}
public function __destruct()
{
$this->save();
}
}
答案 4 :(得分:1)
您可以轻松地将其包装到自己的类中,该类将信息序列化为字符串并且能够操纵数据,例如,添加另一个值,同时注意最多包含10个元素。
可能的用法看起来像,我们假设cookie last 在开始时将包含256:
echo $_COOKIE['last'] = (new StringQueue($_COOKIE['last']))->add(10), "\n";
echo $_COOKIE['last'] = (new StringQueue($_COOKIE['last']))->add(20), "\n";
echo $_COOKIE['last'] = (new StringQueue($_COOKIE['last']))->add(30), "\n";
echo $_COOKIE['last'] = (new StringQueue($_COOKIE['last']))->add(40), "\n";
echo $_COOKIE['last'] = (new StringQueue($_COOKIE['last']))->add(50), "\n";
echo $_COOKIE['last'] = (new StringQueue($_COOKIE['last']))->add(60), "\n";
echo $_COOKIE['last'] = (new StringQueue($_COOKIE['last']))->add(70), "\n";
echo $_COOKIE['last'] = (new StringQueue($_COOKIE['last']))->add(80), "\n";
echo $_COOKIE['last'] = (new StringQueue($_COOKIE['last']))->add(90), "\n";
echo $_COOKIE['last'] = (new StringQueue($_COOKIE['last']))->add(100), "\n";
输出(Demo):
10,256
20,10,256
30,20,10,256
40,30,20,10,256
50,40,30,20,10,256
60,50,40,30,20,10,256
70,60,50,40,30,20,10,256
80,70,60,50,40,30,20,10,256
90,80,70,60,50,40,30,20,10,256
100,90,80,70,60,50,40,30,20,10
粗略实施:
class StringQueue implements Countable
{
private $size = 10;
private $separator = ',';
private $values;
public function __construct($string) {
$this->values = $this->parseString($string);
}
private function parseString($string) {
$values = explode($this->separator, $string, $this->size + 1);
if (isset($values[$this->size])) {
unset($values[$this->size]);
}
return $values;
}
public function add($value) {
$this->values = $this->parseString($value . $this->separator . $this);
return $this;
}
public function __toString() {
return implode(',', $this->values);
}
public function count() {
return count($this->values);
}
}