如何记住Codeigniter中用户在会话中使用时间戳的10篇最后阅读文章?

时间:2012-12-18 19:08:28

标签: php codeigniter session cookies

我想制作一个 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篇文章;)

5 个答案:

答案 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()项目是否可以节省时间。

请记住:

  • 每件商品将在10分钟后过期(参见$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);
    }
}

这只是一些基本的字符串操作,这里有implodeexplode