ページ 11

PHPにCookieを使った観覧履歴を追加したい

Posted: 2016年1月25日(月) 04:07
by HDD
私は今、PHPを使ってサイトを作っているのですが、サイトを利用した人に観覧履歴が追加出来たらなと思い、Cookieを利用して構築を試みようとしています。
観覧したら、Cookieの配列に値を追加していき、Cookieの配列に空きがなくなれば、古い要素の配列から消去し、要素0に履歴を追加するコードを組みました。

コード:

<?php
$id = isset($_GET['ID']) ? $_GET['ID'] : null; //GETでIDを受け取る
/* cookieに登録を行う */
//cookieの配列の要素に空きがあれば$idを格納する
    if (isset($_COOKIE["history"])){
      $history_id = $_COOKIE["history"];
      for($i = 0; $i <= 4; $i++){
        if(!isset($history_id[$i])){
          setcookie ("history[$i]", $id);
          break;
        }
      }
//cookieの配列に空きがなくなれば、
//$idの値を要素ごとに1つずつずらし、
//要素0に$idを格納する
        if(isset($history_id[4])){
          for($j = 4; $j >= 1; $j--){
            $history_id[$j] = $history_id[$j-1];
      }
              setcookie ("history[0]", $id);
    }

    }
    else{
      setcookie ("history[0]", $id);
    }
?>
上記のようなコードを書きました。

//Cookieの配列の要素に空きがあれば$idを格納する
の処理では、$idを追加していきたいとき、
$history = {}

$history = {0}

$history = {0,1}

$history = {0,1,2}

$history = {0,1,2,3}

$history = {0,1,2,3,4}
とできるのですが、

//Cookieの配列に空きがなくなれば、
//$idの値を要素ごとに1つずつずらし、
//要素0に$idを格納する
の処理がうまいこと動きません
現状では、
$history = {0,1,2,3,4} から$id=6を追加したら、
$history = {6,1,2,3,4} から$id=7を追加したら、
$history = {7,1,2,3,4}
となってしまい、ソートがされません。
正しくは、
$history = {0,1,2,3,4} から$id=6を追加したら、
$history = {6,0,1,2,3} から$id=7を追加したら、
$history = {7,6,0,1,2}
とソートしたいです。

開発環境はMAMPを利用してローカル環境で開発しており、OSはMac OS X Yosemiteです。
Cookieの確認は、chromeから
[設定]→[プライバシー コンテンツの管理]→[すべてのCookieサイト データ...]
からドメインで検索して、Cookieの確認を行っています。

ご回答よろしくお願いします。

Re: PHPにCookieを使った観覧履歴を追加したい

Posted: 2016年1月25日(月) 04:49
by へにっくす
phpはよく知りませんが。
よく見れば
setcookie
を実行することで反映できていることが分かるはず。
$history_id[$j] = $history_id[$j-1];
ではなくて
setcookie ("history[$j]", $history_id[$j-1]);
とやればいいのでは。

駄目でしたらすみません。

Re: PHPにCookieを使った観覧履歴を追加したい

Posted: 2016年1月25日(月) 06:47
by HDD
ありがとうございます。
ソートの問題は解決しました。

コード:

$id = isset($_GET['ID']) ? $_GET['ID'] : null; //GETでIDを受け取る
/* cookieに登録を行う */
//cookieの配列の要素に空きがあれば$idを格納する
    if (isset($_COOKIE["history"])){
      $history_id = $_COOKIE["history"];
      for($i = 0; $i <= 4; $i++){
        if(!isset($history_id[$i])){
            for($k = $i; $k >= 1; $k--){// 追加
              setcookie ("history[$k]", $history_id[$k-1]);
            }
          setcookie ("history[0]", $id);
          break;
        }
      }
//cookieの配列に空きがなくなれば、
//$idの値を要素ごとに1つずつずらし、
//要素0に$idを格納する
        if(isset($history_id[4])){
          for($j = 4; $j >= 1; $j--){
            setcookie ("history[$j]", $history_id[$j-1]);// 変更
      }
              setcookie ("history[0]", $id);
    }
 
    }
    else{
      setcookie ("history[0]", $id);
    }

上記のようにコードを変更し、キュー構造にしてcookieを格納することにしました。

しかし、今のコードのままだと、問題点があり、
$idは同じ値でも重複して登録してしまいます。

$history = {0,1,2,3,4} から$id=1を追加したら、
$history = {1,0,1,2,3} から$id=2を追加したら、
$history = {2,1,0,1,2}

となってしまいます。

$history = {0,1,2,3,4} から$id=1を追加したら、
$history = {1,0,2,3,4} から$id=2を追加したら、
$history = {2,1,0,3,4}

と重複した値を先頭の要素に持ってくるようにソートするにはどうしたらいいでしょうか?

Re: PHPにCookieを使った観覧履歴を追加したい

Posted: 2016年1月25日(月) 14:20
by YuO
私だったら,で済ますのですが,これだと要求を満たさないのでcountが5以上の時はarray_popしてarray_unshiftになるのでしょうか。
オフトピック
これだと履歴としておかしい気はしますが……。
HDDさんが書かれている$historyの中身の「0」は最初の閲覧なので,本来なら履歴「6」が来たときに最初に履歴から消えると思うのですが,HDDさんが書かれているのは履歴の中で最新の「4」を削除する,となっています。
そして,「6」が履歴の末尾まで来たあとに別の履歴が追加されると,恐らく「6」が消えるのでしょう。

普通のローテーションではない履歴管理なので,不思議です。

Re: PHPにCookieを使った観覧履歴を追加したい

Posted: 2016年1月25日(月) 21:14
by zuttomo
入れる配列の中をforループを回して
これから入れる数値と同じ数値がないか探します。
もしあればその数値を配列から消して
末尾にこれから入れる数値を追加って
具合で大丈夫です。

Re: PHPにCookieを使った観覧履歴を追加したい

Posted: 2016年1月26日(火) 12:05
by HDD
2人方の意見を参考にして以下のようなコードを書きました。

コード:


$id = isset($_GET['ID']) ? $_GET['ID'] : null; 
/* cookieに登録を行う */
//cookieの配列の要素に空きがあれば$idを格納する
//新しい値はhistory[0]に書き込まれていく
    if (isset($_COOKIE["history"])){
      $history_id = $_COOKIE["history"];
      for($i = 0; $i <= 19; $i++){
        if(!isset($history_id[$i])){
            for($k = $i; $k >= 1; $k--){
              setcookie ("history[$k]", $history_id[$k-1]);
            }
          setcookie ("history[0]", $id);
          break;
        }
      }
//cookieの配列に空きがなくなれば、
//$idの値を要素ごとに1つずつずらし、
//要素0に$idを格納する
        if(isset($history_id[19])){
          for($j = 19; $j >= 1; $j--){
            setcookie ("history[$j]", $history_id[$j-1]);
      }
              setcookie ("history[0]", $id);
    }
 }
    else{
      setcookie ("history[0]", $id);
    }

//array_searchで配列の中に$idと同じ値があったら
//array_uniqueで重複している値を取り除く
//array_valuesで添字を振りなおす
      if(array_search($id, $history_id) == TRUE){//追加
      $history_id = array_unique($history_id);
      $history_id = array_values($history_id);
      setcookie ("history", $history_id);
    }

しかし、
//array_searchで配列の中に$idと同じ値があったら
//array_uniqueで重複している値を取り除く
//array_valuesで添字を振りなおす
を追加したのですができていません。やっぱり、同じ値が重複して入ってしまいます。

あと、指摘の通り、履歴としてはおかしいと思われたかもしれませんが、No:3のコードでそれは修正してあります。

Re: PHPにCookieを使った観覧履歴を追加したい

Posted: 2016年1月26日(火) 15:12
by YuO
HDD さんが書きました:

コード:

      if(array_search($id, $history_id) == TRUE){//追加[/quote]
[url=http://php.net/manual/ja/function.array-search.php#refsect1-function.array-search-returnvalues]array_search[/url]のヘルプの返り値欄をちゃんと読みましょう。
array_searchは見つかったらTRUEを返すような設計になっていません。
見つかればその添字を,見つからなかったらFALSEを,それぞれ返します。
このため,この実装では$idが配列$history_idのインデックス1 (or それ相当:'1a'等) で見つかる時のみifの中を実行します。
そもそも,見つかろうが見つかるまいが,[url=http://php.net/manual/ja/function.array-unique.php]array_unique[/url]を実行すれば一意になるのですから,array_searchを呼び出す必要はないです。