2

ユーザーが記事を読んでから過去10記事もしくは10分が経過したかどうかをチェックするPHP if条件コードを作りたいです。

例えば

ユーザーが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 エントリを保存するだけで十分だと思います。

セッションで同じページを 2 回保存しないでください。

そして、条件は保存されたタイムスタンプで現在のタイムスタンプをチェックし、たとえば 10 分以上であるか、ユーザーが別の 10 の記事を読んだりクリックしたりした場合は、更新カウンター php コードを許可します。

私はこの防弾を持っている必要はありません。ブラウザの更新ボタンを使用してインクリメントを無効にするだけです。

したがって、カウンターを増やしたい場合は、10 分待つか、さらに 10 個の記事を読む必要があります ;)

4

5 に答える 5

4

あなたは間違いなくセッションに行くべきです。帯域幅の消費を節約し、処理がはるかに簡単になります。もちろん、クライアント側でデータが必要な場合を除きますが、あなたの説明では、そうではないと思います。セッションに行ったと仮定すると、あなたがしなければならないことは、持っているデータを配列に保存することだけです。次のコードでそれを行う必要があります。

$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
}
于 2012-12-18T19:57:10.767 に答える
2

$clicks は、最大 10 個の訪問済み記事を含む配列であると想定しています。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";
}

編集: rsortではなくarsortを使用する必要があります。そうしないと、キーが失われます。申し訳ありません

于 2012-12-22T14:42:31.023 に答える
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();
        }
    }
    
于 2012-12-26T15:28:07.660 に答える
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!";

        }
    ?>
于 2012-12-21T09:19:47.993 に答える
1

情報を文字列にシリアル化し、データを操作できる独自のクラスに簡単にラップできます。たとえば、最大 10 要素に制限しながら別の値を追加できます。

考えられる使用法は次のようになります。Cookieの最後に開始時に 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);
    }
}

これは、いくつかの基本的な文字列操作です。ここではimplodeとを使用してexplodeいます。

于 2012-12-27T12:47:08.823 に答える