HTMLで表示しているcheckboxのチェック状態を、保存ボタンを押すと保存できるようにしたいと考えています。

この際、画面推移することなく、保存後はそのチェック状態を保って、次の作業を行うことができるようにするには、Ajaxを使う必要があるということが分かり、コードの書き方の勉強を始めていますが、頭がすっきり整理されてない状態です。

以下のcheckboxのチェック状態をAjaxで保存する場合、どういったコードを書く必要があるのでしょうか?
今後の勉強の礎にさせて頂きたいと思いますので、よろしくお願いしますm(_ _)m
(PHPやJavaScriptの知識は初心者程度です)

*HTML
<input id="time_1" name="time[]" type="checkbox" value="morning">朝
<input id="time_2" name="time[]" type="checkbox" value="noon">昼
<input id="time_3" name="time[]" type="checkbox" value="evening">夜

回答の条件
  • 1人20回まで
  • 登録:
  • 終了:2011/10/22 13:30:03

ベストアンサー

id:tdoi No.1

回答回数174ベストアンサー獲得回数75

こういうこと?

この前の回答の最初の方をちょっといじっただけですが。


<?php
if (isset($_GET['record'])) {
  $times = $_GET['time'];
  setcookie('times', serialize($times), time() + 30 * 60);
  exit;
}

$time = array();
if (isset($_COOKIE['times'])) {
  $times = unserialize($_COOKIE['times']);
}
?>
<html>
  <head>
    <script type="text/javascript" src="./jquery.js"></script>
    <script language="JavaScript">
<!--
function recordTime()
{
  var checkList = new Array(document.getElementById('morning'),
			     document.getElementById('noon'),
			     document.getElementById('evening'));
  var times = new Array();
  for (i = 0; i < checkList.length; ++i) {
    if (checkList[i].checked) {
      times.push(checkList[i].value);
    }
  }
  $.get("./index.php", { "time[]": times, "record": 1 });
}
-->
    </script>
  </head>
  <body>

    <form action="#">
    <div id ="time">
      <input name="time[]" type="checkbox" value="morning" id="morning" <?php if (in_array('morning', $times)) {?>checked="CHECKED"<?php } ?> >
      <label for="morning">朝</label>
      <input name="time[]" type="checkbox" value="noon" id="noon"  <?php if (in_array('noon', $times)) {?>checked="CHECKED"<?php } ?> >
      <label for="noon">昼</label>
      <input name="time[]" type="checkbox" value="evening" id="evening" <?php if (in_array('evening', $times)) {?>checked="CHECKED"<?php } ?> >
      <label for="evening" >夜</label>
    </div>

    <input type="submit" value="保存" onClick="recordTime(); return false;" />

    </form>    
  </body>
</html>

仕組みとしては、前回の指定のままCookieを使っています。

このPHPスクリプトは、普通にブラウザで表示した際には、最初の5行は実行されません。そして、すでにCookieに登録されているものがあれば、それにチェックを入れたHTMLを表示するようになっています。

チェックを変更して保存ボタンを押した際に、JavaScriptの処理が起動して、recordTime()という関数が実行されます。この中では、現在のチェック状態を取得して、同じスクリプトにjQueryというライブラリを使って送信しています。この送信はバックグラウンドで行われるので画面は切り替わりません。

先頭5行はこの送信に対する処理で、受け取った情報をCookieに書き込んでいます。

例えばですが、この画面をどこかのサーバに置いて、適当にチェックを入れて保存ボタンを押した後、チェックを変更した後リロードすると、保存ボタンを押したときの状態に戻ることが分かると思います。


あまり詳しくないとのことなので、PHP、JavaScriptという言語そのものだけでなく、PHPはサーバサイドで動作し、JavaScriptはクライアントサイドで動作することや、それらの兼ね合い。あるいは、jQueryなどのライブラリの利用など知るべきことはたくさんあると思いますが、がんばってください。

何かの参考になれば。


追記 (10/18 1:42):

パスの指定の問題です。

僕の場合はテスト環境では、index.phpとjquery.jsは同じディレクトリに置いてあったので、./query.jsという指定になっています。index.phpと同じディレクトリにあるjsというディレクトリの中にjquery.jsがあるのであれば、./js/jquery.jsと指定する必要があります。

他にもたくさんあると思いますが、この辺りでも読んでみてはどうでしょう?

http://www.shoshinsha.com/hp/1hour/know/pass.html

id:toshistyle

早速の回答ありがとうございますm(_ _)m

大変分かりやすい説明で、だいぶん頭が整理されました。

引き続き勉強がんばろうと思います。

ありがとうございました。


追記(10/18 1:39):

不足していたことを勉強し、ほぼ理解することができましたが、

一点質問があります。

<script type="text/javascript" src="./jquery.js"></script>の./jquery.jsは、

index.phpにjquery.jsを組み込んでいるということなのでしょうか?

Dreamweaverを使い、jsフォルダにjquery.jsがあるのですが、

js/jquery.jsとするとうまくいきません。

きっと./jquery.jsの部分を正しく理解していないのだと思います。

簡単なことかもしれませんが、よろしくお願いしますm(_ _)m


追記(10/19 11:30):

早速のご回答ありがとうございますm(_ _)m

教えて頂いたコードを参考に、いろいろ試しているのですが、

「適当にチェックを入れて保存ボタンを押した後、チェックを変更した後リロードすると、保存ボタンを押したときの状態に戻る」

ことがどうしてもうまくいきません。

src="./jquery.js" や  form action="#" の部分で何か誤解していることがあるのではないかと考えましたが、この部分では特に問題ないことが分かりました。

クッキーの制限もしておらず、どこに問題があるのか探しているのですが、なかなか解決できずにいます。

原因として考えられることがあれば、教えて頂くと助かります。

重ね重ね申し訳ありません。

2011/10/18 11:30:19
  • id:Lhankor_Mhy
    具体的に何をしたいのか書いてもらったほうが早いかもしれませんね……
     
    -Cookie + Javascript だけでチェックボックスの状態を保存することはできます。
    -保存されたチェックボックスの状態をサーバーに通信したい時は、フォーム(HTTPリクエスト)またはAjaxが必要です。
    -ページ遷移をせずに保存されたチェックボックスの状態をサーバーに通信したい時、Ajaxでなくてはできません。
     
    したいことはどれですか?
    -チェックボックスの状態を保存したいだけ → PHPかJavascriptでCookieを利用する
    -ページ遷移をせずにチェックボックスの状態を保存したい → JavascriptでCookieを利用する
    -ページ遷移をせずにチェックボックスの状態をサーバに保存したい → Ajaxを利用する
     
     
     
    そうしないと、回答者も質問の意図が読み取れず、どう回答していいのか分からなくなります。
    たとえば、id:tdoiさんの回答はAjaxではないです。質問から読み取れる機能にAjaxは必要ないからそのように答えてらっしゃるのだと思いますが、質問者としては満足がいく答えなのか、正直分からないです。

  • id:tdoi
    Lhankor_Mhyさんがおっしゃるように、やりたいことが明確に見えていないのはあります。
    ただ、他の質問を合わせて考えると、「ページ遷移をせずにチェックボックスの状態をサーバ側で利用できる仕組みを構築したい」ということは想像がつきますので、そのような回答になっています。

    Ajaxとは何かを議論する気はないのですが、「ページ遷移をせずにチェックボックスの状態をサーバに保存する」ことを実現する仕組みは提供しています。厳密には、Cookieに保存してますので、サーバ側にはないですが、Cookieが有効な間はサーバにアクセスする際に送付される訳で、ある種サーバ側に保存していることと近いといえるでしょう。

    また、これまでの流れからCookieを使っていますが、やりたいことが明確に見えていないので、これまでの流れに従っているだけです。この方法が最適かどうかは別です。保存したい期間などによっては、セッションだったり、DBだったりと保存方法は色々あります。

    もっとやりたいこと、つまり、保存ボタンを押した後何をしたいのか?を書いて頂ければ、この辺りもアドバイスはできるかと思います。保存をした後、他のページを見た後遷移したいのか、途中でやめてブラウザを閉じたりした場合でも再現できるようにしたいのか、などなどです。


    保存の方法と、データのやり取りの方法とは別の話しなので、混同されないように気をつけてくださいね。
  • id:tdoi
    保存されない理由としては、もしローカルの環境であれば、次のことが関係してるかもしれません。
    http://www.phppro.jp/qa/1055

    あとは、どこがおかしいのかを切り出すために、スクリプトの先頭にでも、

    print_r ($_COOKIE);

    を書いておくとか、スクリプトの最後の方にでも、

    print_r ($times);

    を書いて置くなどをして、問題を切り分けるのがいいかと思います。

    以下のどの状況が起きているかが分かることによって原因も特定しやすくなると思います。

    1.保存にそもそも失敗している。
    2.保存は成功しているが、リロードした際に情報が失われる。
    3.保存もリロード後のデータ復帰も成功しているが、チェックボックスに反映がされない。
    4.その他(times以外のものの影響で何か悪さしてるとか)

  • id:toshistyle
    print_r ($_COOKIE);を先頭に書いたところ、
    Array ( [times] => a:1:{i:0;s:7:\"morning\";} [__utma] => 95259166.156071816.....
    と表示されるので、
    1.保存にそもそも失敗している。

    4.その他(times以外のものの影響で何か悪さしてるとか)
    に該当するのではないかと思っています。
    さくらのレンタルサーバにある仕様書などを読んで解決しようとしたのですが、
    なかなか何が問題なのか理解できません。
    予想される問題点を指摘して頂ければ助かりますm(_ _)m

    また.htaccessファイルでトップページindex.phpを指定することはできました。
    ありがとうございました。

  • id:tdoi
    もし、朝にだけチェックを入れて上記の内容が表示されるなら、保存には成功していそうですね。
    a:1:{i:0;s:7:\"morning\";}
    というのは、
    array("morning")
    をシリアライズした結果です。
    $times = unserialize($_COOKIE['times']);
    のあとで、
    print_r ($times);
    をするとどうなります?
  • id:toshistyle
    早速の返信ありがとうございますm(_ _)m

    何も表示されないです。
    $times = unserialize($_COOKIE['times']);の直後、
    $times = unserialize($_COOKIE['times']); }の直後と何回か試しましたが、
    表示されませんでした。
  • id:tdoi
    確認ですが、
    print_r ($_COOKIE)で、Array ( [times] => a:1:{i:0;s:7:\"morning\";} [__utma] => 95259166.156071816.....
    と表示されるにも関わらず、
    $times = unserialize($_COOKIE['times']);
    print_r($times);
    には何も表示されないということでいいですか?
    つまり、両方にprint_r(xxx)を書いておくと、

    Array ( [times] => a:1:{i:0;s:7:\"morning\";} [__utma] => 95259166.156071816.....
    ---本来のHTMLの画面----

    のように表示されるということですか?

    コード見ないとなんともですが、もしそうなら、次のことを試してみてください。

    1.error_reporting(E_ALL);と先頭に書いておく。

    2.デシリアライズの部分のコードを、
    $tmp = $_COOKIE['times'];
    print_r ($tmp);
    $times = unserialize($tmp);
    if ($times === false) {
    echo "unserialize failed.";
    }
    print_r ($times);
    のように2段に分けて見て下さい。
    どこかでtypoか、もしくは、unserializeに失敗しているのかが分かるはずです。
  • id:toshistyle
    tdoiさんのおっしゃる通り、両方にprint_r(xxx)を書いておくと、
    Array ( [times] => a:1:{i:0;s:7:\"morning\";} [__utma] => 95259166.156071816.....
    ---本来のHTMLの画面----
    のように表示されます。

    1と2をコードに書いた結果、
    Array ( [times] => a:1:{i:0;s:7:\"morning\";} [__utma] => 95259166.1560718168.1318928771.1318928771.1319102814.2 [__utmc] => 95259166 [__utmz] => 95259166.1319102814.2.2.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=さくらのレンタルサーバ ) a:1:{i:0;s:7:\"morning\";}unserialize failed.
    と表示され、デシリアライズ失敗のようです。

    この辺のコードは初めて見るもので、理解することができません。
    申し訳ありませんが、ご指示よろしくお願いしますm(_ _)m


  • id:tdoi
    これは動きますか?

    $t = "a:1:{i:0;s:7:\"morning\";}";
    echo $t;
    $r = unserialize($t);
    print_r ($r);
    echo serialize($r);

    画面に\が表示されるのはちょっと変な気もしてきましたが。
  • id:toshistyle
    a:1:{i:0;s:7:"morning";}Array ( [0] => morning ) a:1:{i:0;s:7:"morning";}
    と表示されています。
    正しく動いていると思います。
  • id:tdoi
    では、print_r ($_COOKIE)で、
    Array ([times] => a:1:{i:0;s:7:"morning";・・・);
    ではなく
    Array ([times] => a:1:{i:0;s:7:\"morning\";・・・);
    と画面上に表示されることが問題かもですね。

    もし、回答のコードと同じ構造をしているならですが、
    if (isset($_GET['record'])) {
    $times = $_GET['time'];
    setcookie('times', serialize($times), time() + 30 * 60);
    exit;
    }
    のとろこを、
    if (isset($_GET['record'])) {
    $times = $_GET['time'];
    print_r($times);
    $tmp = serialize($times);
    echo $tmp;
    setcookie('times', $tmp, time() + 30 * 60);
    exit;
    }
    として、
    index.php?record=1&times[]=morning&times[]=noon
    みたいな感じでアクセスしてみてください。
    index.phpのところは適宜読み替えて下さいね。
  • id:toshistyle
    Array ( [times] => a:1:{i:0;s:7:\"morning\";} [__utma] => 95259166.1560718168.1318928771.1318928771.1319102814.2 [__utmc] => 95259166 [__utmz] => 95259166.1319102814.2.2.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=さくらのレンタルサーバ ) N;

    と表示されました。
    a:1:{i:0;s:7:\"morning\";}unserialize failed.だった部分がNになりました。
  • id:tdoi
    失礼。直して再度試してみてください。
    正:
    $times = $_GET['times'];

    $times = $_GET['time'];

    期待通りに動けば、
    Array([0] => morning, [1] => noon) a:2:{i:0;s:7:"morning";i:1;s:4:"noon";}
    と表示されると思います。
    紛らわしいので、print_r($_COOKIE)は一度コメントアウトしておきましょうか。
  • id:toshistyle
    Array ( [0] => morning [1] => noon ) a:2:{i:0;s:7:"morning";i:1;s:4:"noon";}
    と期待通りに表示されました。
  • id:tdoi
    では、普通にindex.phpにアクセスすると、さっきのアクセスでCookieが正しく保存されているはずなので、コメントのように書き換えて貰っていれば、

    a:2:{i:0;s:7:"morning";i:1;s:4:"noon";} Array ( [0] => morning [1] => noon )

    と出ると思うのですが、やっぱり、unserialize failedって出ます?
  • id:toshistyle
    コメント通りに行いましたが、
    a:1:{i:0;s:7:\"morning\";}unserialize failed.
    と表示されました><
  • id:tdoi
    原因は良く分かりませんが、エスケープされてしまうのが問題ですね。
    とりあえずは、デシリアライズのところを、以下のようにしたら動くんじゃないかと思うんですがどうでしょう?
    $tmp = $_COOKIE['times'];
    print_r ($tmp);
    $tmp = stripslashes($tmp);
    print_r ($tmp);
    $times = unserialize($tmp);
    if ($times === false) {
    echo "unserialize failed.";
    }
    print_r ($times);
    期待通りに動けば、
    a:1:{i:0;s:7:\"morning\";}a:1:{i:0;s:7:"morning";}Array ( [0] => morning [1] => noon )
    と出るかと思いますが。
  • id:toshistyle
    a:1:{i:0;s:7:\"morning\";}a:1:{i:0;s:7:"morning";}Array ( [0] => morning )
    と表示されました。
    長時間にわたって、本当にありがとうございますm(_ _)m
  • id:tdoi
    では、チェックもうまく保存されましたよね?
    問題なければ、デバッグ用に追加したprint_r(xx)を消せばOKですよね?
  • id:toshistyle
    保存されています。
    帰宅しないといけないので、
    ちょっと頭を整理して、
    またコメントさせて頂きます。
  • id:tdoi
    マジッククォートはCookieにも影響するんですね。
    ちょっと整理すると、

    $times = $_COOKIE['times'];
    if (get_magic_quotes_gpc()) {
    $times = stripslashes($times);
    }
    $times = unserialize($times);

    とでもしてやるのが正しそうですね。
  • id:toshistyle
    昨日は長時間にわたるご指導本当にありがとうございましたm(_ _)m

    また質問で大変恐縮なのですが、
    教えて頂いた通りにコードを修正した結果、
    value=morningのcheckboxにずっとチェックがついた状態になっています。
    noonやeveningに該当するcheckboxにチェックをつけて保存ボタンを押し、
    リロードしたり新たにブラウザを開いたりしても、
    ずっとmorningにだけチェックがついた状態です。
    チェック状態を保存ボタンを押した時点の状態で保存するには、
    どの部分のコードをいじればよいのでしょうか?
    もしくはコードは修正する必要がなく、
    何か勘違いをしているのでしょうか?

    ご指摘して頂ければ助かります。
    よろしくお願いしますm(_ _)m

  • id:tdoi
    チェック状態は保存されたのではないのですか?

    確認するとすれば、昨日のように、
    1.$_COOKIEに期待通りの値が入っているか?
    2.$timesの値が期待通りになっているか?
    3.期待通りにチェックボックスにチェックが入るか?
    という3つに問題を分割してください。昨日の流れだと1と2は大丈夫だと思ってたのですが。

    もし、3だけが実現できていないとかなら、以下のような部分の表示の問題です。

    <input name="time[]" type="checkbox" value="evening" id="evening" <?php if (in_array('evening', $times)) {?>checked="CHECKED"<?php } ?> >

    テストのために

    <?php if (in_array('evening', $times)) { echo 'eveningはチェックされてます'; } ?>

    みたいにしてみるのもよいかもしれません。
  • id:toshistyle
    申し訳ありません。勘違いをしていました。
    チェック状態はcookieにきちんと保存されています。
    その保存したcookieを削除できる機能が必要なのでした。
    javascriptやPHPで実装できそうなので、挑戦してみます。
    もう少しで必要な機能が揃いそうです。
    いろいろと理解不足で申し訳ありませんでしたm(_ _)m

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません