質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.03%

PHPでCookieを使用した値の追加と削除について教えて下さい!

解決済

回答 4

投稿

  • 評価
  • クリップ 2
  • VIEW 4,348

score 35

PHPを最近始めたばかりの初心者です。
ご教授の程、どうぞ宜しくお願い致します!m(__)m

早速ですが、商品一覧のページを作成しました。
下記のように商品毎にそれぞれ「お気に入り追加」というアンカーを設置しています。
<!-- index.php -->

<ul>
   <li>商品1</li>
   <li><a href="favorite.php?keep_in=10001">お気に入り追加</a></li>
   <li>商品2</li>
   <li><a href="favorite.php?keep_in=10002">お気に入り追加</a></li>
   .
   .
   .
</ul>
「お気に入り追加」をクリックするとCookieに商品IDを追加して行き、
もう一度「お気に入り追加」をクリックで商品IDを削除するにはどうしたら良いでしょうか?

setcookieで配列にして記憶させておいて、再度「お気に入り追加」をクリックで keep_in と同じ値が既にCookieにある場合は、該当する配列を削除する様にしたら良いのでしょうか?

// favorite.php

if (isset($_GET['keep_in'])) {
    $value = $_GET['keep_in'];
    setcookie("KeepID[$value]", $value, time()+60*60*24*30, "/");
}

お気に入り追加を行った商品の保存期間は30日として設定しています。

後々やりたいことになりますが、Cookieで記録した配列はPDOでプレースホルダーにして
MySQLで商品詳細として抽出し表示したいと思っています。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+4

シリアライズすれば良いと思います。

$keeplist[$value] = $value;
setcookie("keeplist", serialize($keeplist), time()+60*60*24*30, "/");

取り出すときはデシリアライズします。

$keeplist = unserialize($_COOKIE["keeplist"]);

例外処理とか無視した最小限で書くと下記のような感じです。

<?php
$keeplist = array();

if (isset($_COOKIE['keeplist'])) {
    $keeplist = unserialize($_COOKIE["keeplist"]);
}

if (isset($_GET['keep_in'])) {
    $value = $_GET['keep_in'];
    if (isset($keeplist[$value])) {
        unset($keeplist[$value]);
    } else {
        $keeplist[$value] = $value;
    }

    setcookie("keeplist", serialize($keeplist), time()+60*60*24*30, "/");
}

var_dump($keeplist);

コメントにもある通り、クッキーのような外部からくる値を unserialize するのは危険なので json_encode/json_decode を使うほうが良いです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/03/26 22:23

    ArimaRyunosuke様、ngyuki様、補足コメントありがとうございます。

    早速、参考URLを拝見しました。
    将来、脆弱性になりかねないですね・・・(汗)

    jsonで代替するとなると、このようにして使用したら良いでしょうか?

    誤)setcookie("keeplist", serialize($keeplist), time()+60*60*24*30, "/");

    誤)$keeplist = unserialize($_COOKIE["keeplist"]);


    正)setcookie("keeplist", json_encode($keeplist), time()+60*60*24*30, "/");

    正)$keeplist = json_decode($_COOKIE["keeplist"]);

    キャンセル

  • 2015/03/27 09:45

    実際にやってみればわかると思いますが json_decode の第2引数に true を指定しないと stdClass になってしまうので上手く動きません

    キャンセル

  • 2015/03/27 23:04

    ngyuki様
    再補足ありがとうございます!
    true有りで配列ということですね。
    最終的にこうなりました。
    $keeplist = json_decode($_COOKIE["keeplist"], true);

    キャンセル

+1

ごめん、余計なことした、cookie のときは [] 使えないんだね
    if( isset( $_GET[ 'keep_in' ] ) ) {
        if( array_key_exists( 'KeepID', $_COOKIE ) && ( $p = array_search( $_GET[ 'keep_in' ], $_COOKIE[ 'KeepID' ] ) ) !== false ) {
            // Delete value from cookie.
            setcookie("KeepID[{$p}]", '', time() - 3600, '/');
            unset($_COOKIE['KeepID'][$p]);
        } else {
            // Add value in cookie.
            $value = $_GET[ 'keep_in' ];
            setcookie("KeepID[{$value}]", $value, time() + 2592000 /*60*60*24*30*/, '/');
        }
    }
    
    var_dump( $_COOKIE );

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/03/26 11:44

    ご回答ありがとうございます。m(__)m

    Cookieの場合は[]配列記述が使用できないのですね。
    必ず配列キーを設定しなくてはいけないのですね(^o^;

    array_key_exists()やarray_search()は様々なシーンで使えそうですね。

    miya様、ngyuki様 御二方のご教示により上手く解決することが出来ました。
    両者ともベストアンサーにしたいのですがシステム上、それは無理そうですね?(^o^;
    今回はシンプルな方法をご教示頂いたngyuki様をベストアンサーにしたいと思います。(miya様、大変申し訳ございませんm(__)m)

    setcookie("KeepID[{$value}]", $value, time() + 2592000 /*60*60*24*30*/, '/');

    最後に気になったのですが
    こちらのsetcookieで有効期間が60*60*24*30の答えが秒数で記述されていますが
    答え(2592000)を記述することによって処理速度も向上するのでしょうか?

    キャンセル

0

if ( isset( $_GET[ 'keep_in' ] ) ) {
  if ( ( $p = array_search( $_COOKIE[ 'KeepID' ], $_GET[ 'keep_in' ] ) ) !== false ) {
    // Delete value from cookie.
    setcookie( "KeepID[{$p}]", '', time() - 3600, '/' );
    unset( $_COOKIE[ 'KeepID' ][ $p ] );
  } else {
    // Add value in cookie.
    setcookie( 'KeepID[]', $_GET[ 'keep_in' ], time() + 2592000/*60*60*24*30*/, '/' );
  }
}

KeepID[] = ~ ってすると自動で連番振って新しい要素追加してくれる。
お気に入りとかもデータベース管理したほうがいいと思うけど、登録とかしなきゃいけなくなるからね
俺なら場合によっては登録以外の方法取るけど

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/03/24 21:16

    miya様、ご回答ありがとうございます!

    早速、miya様の方法で記述してみたところ下記のエラーが表示されてしまいました。

    【HTML側】
    <html>
    <head>
    <body>
    <a href="/favorite.php?keep_in=10001">お気に入り</a>
    <a href="/favorite.php?keep_in=10002">お気に入り</a>
    </body>
    </html>


    【PHP側】

    <?php
    if ( isset( $_GET[ 'keep_in' ] ) ) {
    if ( ( $p = array_search( $_COOKIE[ 'KeepID' ], $_GET[ 'keep_in' ] ) ) !== false ) {
    // Delete value from cookie.
    setcookie( "KeepID[{$p}]", '', time() - 3600, '/' );
    unset( $_COOKIE[ 'KeepID' ][ $p ] );
    } else {
    // Add value in cookie.
    setcookie( 'KeepID[]', $_GET[ 'keep_in' ], time() + 2592000/*60*60*24*30*/, '/' );
    }
    }
    ?>



    ▼ 下記エラーになります。

    if ( ( $p = array_search( $_COOKIE[ 'KeepID' ], $_GET[ 'keep_in' ] ) ) !== false ) {

    この行で下記のエラーが表示されました。
    「Notice: Undefined index: keepID in~..」
    「Warning: array_search() expects parameter 2 to be array, string given in~..」

    setcookie( "KeepID[{$p}]", '', time() - 3600, '/' );

    こちらの行で下記のエラーが表示されました。
    「Warning: Cannot modify header information - headers already sent by (output started at~..」

    キャンセル

  • 2015/03/24 22:08

    あ、ここに書けばいいのかw

    ついでにもう少し修正

    ```lang-<PHP>
    if ( isset( $_GET[ 'keep_in' ] ) ) {
    if ( is_array( $_COOKIE[ 'KeepID' ] ) && ( $p = array_search( $_COOKIE[ 'KeepID' ], $_GET[ 'keep_in' ] ) ) !== false ) {
    // Delete value from cookie.
    setcookie( "KeepID[{$p}]", '', time() - 3600, '/' );
    unset( $_COOKIE[ 'KeepID' ][ $p ] );
    } else {
    // Add value in cookie.
    setcookie( 'KeepID[]', $_GET[ 'keep_in' ], time() + 2592000/*60*60*24*30*/, '/' );
    }
    }
    ```

    あのままだと一発目コケるからね

    キャンセル

  • 2015/03/24 22:13

    is_array( $_COOKIE[ 'KeepID' ] ) ⇒ array_key_exists( 'KeepID', $_COOKIE ) か

    キャンセル

0

ごめんなさい、逆でした

array_search( $_GET[ 'keep_in' ], $_COOKIE[ 'KeepID' ] )

setcookie で表示されたエラーは、array_search のエラー出力が原因です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/03/25 19:51

    再度ご回答有難う御座います!(^^)

    下記のようにif(isset($_COOKIE['KeepID']) してクッキーがセットされているか分岐させてみました。

    // お気に入りクリック
    if(isset($_GET['keep_in'])) {

    // クッキーがセットされているか
    if (isset($_COOKIE['KeepID'])) {

    if(array_key_exists($_GET['keep_in'], $_COOKIE['KeepID']) && ($p = array_search($_GET['keep_in'], $_COOKIE['KeepID'])) !== false) {
    echo $ke = array_search($_GET['keep_in'], $_COOKIE['KeepID']);
    // Delete value from cookie.
    setcookie("KeepID[{$p}]", '', time() - 3600, '/');
    unset($_COOKIE['KeepID'][$p]);

    } else {
    // Add value in cookie.
    setcookie('KeepID[]', $_GET['keep_in'], time() + 2592000 /*60*60*24*30*/, '/');
    }

    } else {
    // Add value in cookie.
    setcookie('KeepID[]', $_GET['keep_in'], time() + 2592000 /*60*60*24*30*/, '/');
    }
    }


    早速、「お気に入り追加」を下記の順番でクリックしていきました。

    【HTML】
    <a href="/favorite.php?keep_in=10001">お気に入り</a>
    <a href="/favorite.php?keep_in=10002">お気に入り</a>
    <a href="/favorite.php?keep_in=10003">お気に入り</a>
    <a href="/favorite.php?keep_in=10004">お気に入り</a>

    10004~10004迄それぞれクリックして、foreach文で配列から取り出して確認してみましたら10004のみしか取り出せませんでした。


    foreach ($_COOKIE["KeepID"] as $value) {
    echo $value . "<br>";
    }

    10001
    10002
    10003
    10004
    と言う様にクリックした分を配列に追加して
    再度同じ番号がクリックされたら該当する番号を削除したいです。

    すみません、何度もお手数かけますが
    どうぞ宜しくお願い致します!m(__)m

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る