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

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

ただいまの
回答率

90.62%

  • PHP

    19756questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • jQuery

    6521questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • Ajax

    1064questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

会員登録なしでお気に入り機能を実装したい ajax

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,140

brebre

score 21

【概要】
会員登録なしでもお気に入り機能を実装したい

【現状】
お気に入りに追加するボタンを押すことで、お気に入りへの追加はできる。
また、リロード後にもう一度押すとお気に入りから削除もできる。

【問題点】
・お気に入りに追加後、リロードせずにもう一度同じボタンを押すと、
「お気に入りの削除」ではなく、再度「お気に入りへの追加」が起こってしまう。
・お気に入りの削除も同様。

【実現したいこと】
・ページ遷移やリロードせずにお気に入りの追加・削除ができるようにしたい。

【現在のコード】

index.php
(headや細かい点は省略)

<?php
    session_start();
    require_once("config.php");

    $favorite = explode("/",$_COOKIE["favorite"]);
?>

<script>
$(".favborite_btn").find("a").click(function(){
        if($(this).hasClass('add_fav')) {
            $(this).text("お気に入りに追加");
            $(this).removeClass('add_fav');
            $(this).unbind("click");
        } else {
            $(this).text("お気に入り");
            $(this).addClass('add_fav');
            $(this).unbind("click");
        }
    });
</script>

<div class="favorite_btn">
                        <?php if(!in_array(1, $favorite)): ?>
                        <a onClick="add_fav(1); ?>); return false;">お気に入りに追加</a>
                        <?php else: ?>
                        <a onClick="remove_fav(1); return false;" class="add_fav">お気に入り</a>
                        <?php endif; ?>
</div>
function add_fav(id){
    $.ajax({
        type: "POST",
        url: "add_favorite.php",
        data: {
            "id" : id
        },
        success: function(data){
            alert("お気に入りに追加しました");
        }
    });
}
function remove_fav(id){
    $.ajax({
        type: "POST",
        url: "remove_favorite.php",
        data: {
            "id" : id
        },
        success: function(data){
            alert("お気に入り削除");
        }
    });
}

add_favorite.php

<?php
require_once("config.php");

    $favorite = "";
    if ( isset($_COOKIE["favorite"]) && isset($_POST["id"]) ) {
        $favorite .= $_COOKIE["favorite"];
        $favorite .= "/" . $_POST["id"];
    } else if ( isset($_POST["id"]) ) {
        $favorite .=  $_POST["id"];
    }

    setcookie("favorite", $favorite, time() + 60*60*24);

?>

remove_favorite.php

<?php
session_start();

    $favorite = explode("/",$_COOKIE["favorite"]);
    if (count($favorite) > 0) {
        $idx = 0;
        foreach ($favorite as $val) {
            if ($val == $_POST["id"]) {
                unset($favorite[$idx]);
            }
            $idx++;
        }
    }
    $favorite_str = implode("/", $favorite);
    setcookie("favorite", $favorite_str, time() + 60*60*24);


?>

希望する機能を実装するためのコード等をご教授いただけますと幸いです。
よろしくお願いいたします。

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+4

config.phpに何が書いてあるか気になるところではありますが、
有効期限があるCOOKIEやSESSIONではなくブラウザ側に保管するLocalStorageを利用されては?
javascriptなどで明示的に削除するかユーザー自身がブラウザの開発ツールで削除(かブラウザ自体をアンインストール)するまでは永続的です。

 サンプルソース

Cookie読む部分とHTML(<?php冒頭と途中のHTML省略)

$favorite = [];
if(array_key_exists("favorite",$_COOKIE)){
    $favorite = explode("/",$_COOKIE["favorite"]);
}

$add_disp = "";
$remove_disp = "";
$none = ' style="display:none;"';
if(!in_array(1, $favorite)){
    $remove_disp = $none;
}else{
    $add_disp = $none;
}
?>
<div class="favorite_btn">
    <a onClick="add_fav(1); return false;" id="add_fav"<?=$add_disp?>>お気に入りに追加</a>
    <a onClick="remove_fav(1); return false;" id="remove_fav"<?=$remove_disp?>>お気に入り</a>
</div>

ajaxに送る部分

function add_fav(id){
    $.ajax({
        type: "POST",
        url: "add_fav.php",
        data: {
            "id" : id
        },
        success: function(data){
            $("#remove_fav").show();
            $("#add_fav").hide();
            alert("お気に入りに追加しました");
        }
    });
}
function remove_fav(id){
    $.ajax({
        type: "POST",
        url: "remove_fav.php",
        data: {
            "id" : id
        },
        success: function(data){
            $("#remove_fav").hide();
            $("#add_fav").show();
            alert("お気に入り削除");
        }
    });
}

cssのadd_favクラスが何を指定しているか分かりませんが、
もしshow,hideしていたり何かしらボタン装飾しているようであれば、click時のイベントでclassの付け外しするのではなく、
ajaxのsuccessを以てclassの付け外しすべきと思います。
万が一、ajaxが失敗した際に、「追加しました」「削除しました」の文言がalertされないのに
装飾が変わっているということがあるのではと思います。

と、いうか、ご提示の組み方だとどちらかしかHTMLに出てないので、画面をリロードしない限りは
リンクの見た目は変わってても、ajaxが片方しか呼び出されないようになっていると思いますよ。
つまり、COOKIEに保存前だと常に「お気に入りへの追加」だけが起こっている状況ですね。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/19 15:40

    ご回答いただきありがとうございます。

    config.phpには特別な記述はないので、今回は無視していただいて良いかと思います。

    おっしゃるように、LocalStorageを利用した方が良いとは思うのですが、可能であれば上記のコードを修正し、COOKIEを用いて実装したいと考えております。

    もしご教示いただけるのであれば、よろしくお願いいたします。

    キャンセル

  • 2017/09/19 15:52

    了解です。少しお待ちください。
    ただajaxで「add_fav.php」で呼び出しておきながら質問本文では「add_favorite.php」と書かれています。どちらが正しいのでしょうか?

    キャンセル

  • 2017/09/19 15:56

    > <a onClick="add_fav(1); ?>); return false;">お気に入りに追加</a>

    この部分、 HTMLおかしくないですか?

    キャンセル

  • 2017/09/19 15:58

    初期アクセス時はCOOKIEにfavoriteがないのでissetとかarray_key_existsとかで確認しておいたほうが良いですね。
    たぶん、HTML直せば想定通りに動きます。
    ブラウザの開発ツールでエラー出てますよね。

    キャンセル

  • 2017/09/19 16:01

    上記踏まえて「私ならこう書く」サンプルコードを提示しますので少々お待ちを。

    キャンセル

  • 2017/09/19 16:56

    申し訳ございません。add_fav.phpではなく、add_favorite.phpが正しいです。

    サンプルコードをご提示いただけるとのこと、ありがとうございます。
    お手数おかけしますがよろしくお願いいたします。

    キャンセル

  • 2017/09/19 17:19

    既に提示済みですのでご確認ください。
    今回はそもそもHTMLにミスがあったことでjavascriptが正常に動作していないことが原因でした。
    htmlコードの中にphpコードを混在させる場合は、なるべく簡潔な内容にとどめて置いた方がミスが減り、可読性も良くなります。
    私が提示したコードでは「変数をechoする」のみとしてifなどのロジック部分は冒頭で済ますようにしています。

    キャンセル

  • 2017/09/19 17:23

    > add_fav.phpではなく、add_favorite.phpが正しいです。

    すみません。サンプルコードでは上記は加味していないので、
    私のサンプルコードを利用される際はご自身の環境にあわせて調整してください。

    キャンセル

  • 2017/09/20 21:32

    ご提示いただきましたコードを試してみたところ、希望する動きを実現できました。
    ありがとうございました!

    キャンセル

+1

ちょっと状況がわからないのですが
とりあえずセッションで1アクセスに対する継続性は担保できるでしょう
ただしユーザー登録がなければそのユーザーが継続的にアクセスしているか
どうかは判断できません
セッションの有効期限がきれれば別ユーザーと判断されるでしょう

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/19 15:42

    しっかりとしたお気に入り機能であればユーザー登録等検討すべきだと思います。

    ただ、今回は可能であればCOOKIEで実装したいと考えており、もし上記のコードを修正するだけで実装できるならそうしたいところです。

    ご教授いただけますと幸いです。
    よろしくお願いいたします。

    キャンセル

0

COOKIEに保存するだけならajaxは不要だと思います。
http://qiita.com/takanorip/items/4e23b803bb1393176636

PHP側でCOOKIE保存以外の処理もする予定で、Ajaxも必須要件なのでしょうか?


以下追記

COOKIEの操作をするだけなら、Ajaxで通信挟むよりJavaScriptだけで完結したほうが通信リソース/サーバリソースを使わないのでいいと思います。

これ以上は本題から外れてしまうため、Ajax使わない場合のサンプルだけ提示します。

動作デモ
https://jsfiddle.net/2kkphpyd/

<a href="#" class="favorite add_fav" data-id="1">お気に入りに追加</a><br>
<a href="#" class="favorite add_fav" data-id="2">お気に入りに追加</a><br>
<a href="#" class="favorite add_fav" data-id="3">お気に入りに追加</a><br>
$(function(){
  $(".favorite").on('click', function(){
    if ($(this).hasClass("add_fav")) {
      addFavorite( $(this).data('id'));
      elementLookFavorite(this, true);
    } else {
      deleteFavorite( $(this).data('id'));
      elementLookFavorite(this, false);
    }

    return false;
  });

  var elementLookFavorite = function(targetElement, isfavorite) {
    if (isfavorite) {
      $(targetElement).text("お気に入り解除");
      $(targetElement).toggleClass('add_fav', false);
    } else {
      $(targetElement).text("お気に入りに追加");
      $(targetElement).toggleClass('add_fav', true);
    }
  };

  var addFavorite = function(id) {
    var fav = loadCookieFavorite();
    if (fav.indexOf(String(id)) === -1) {
        fav.push(id);
        saveCookieFavorite(fav);
    } else {
      window.alert('すでにお気に入りに入っています');
    }
  };

  var deleteFavorite = function(id) {
    var fav = loadCookieFavorite();
    var idx = fav.indexOf(String(id));
    if (idx !== -1) {
        fav.splice(idx, 1);
        saveCookieFavorite(fav);
    }
  };

  var saveCookieFavorite = function(favArr) {
      document.cookie = "favorite=" + favArr.join('/');
  };

  var loadCookieFavorite = function() {
    var cookies = document.cookie.split(';')

    for (idx in cookies) {
      if ( ! cookies.hasOwnProperty(idx)) {
        continue;
      }

      if (cookies[idx].indexOf('favorite=') == 0) {
        var favStr = cookies[idx].substr('favorite='.length);
        return (favStr.length==0) ? [] : favStr.split('/');
      }
    }

    return [];
  };
});

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/20 21:33

    コードまでご提示いただきありがとうございます。
    おっしゃるようにAjaxは必須ではないかもしれません。
    今回は既存のコードとの兼ね合いからAjaxを利用した内容で実装しましたが、今後は効率性等考えてコーディングしようと思います。
    ありがとうございました!

    キャンセル

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

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

関連した質問

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

  • PHP

    19756questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • jQuery

    6521questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • Ajax

    1064questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。