I-know-way
@I-know-way (I-know-way admin)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

XMLHttpRequestでの変数受け渡しができません

やりたいこと

window.promptを利用し、ユーザーに希望ユーザー名を入力してもらう(実装済み)
②XMLHttpRequestを使用して、希望ユーザー名を別ページのPHPファイルに送りたい(ここで困っています)
③PDOを使用し、SQLのデータベースに希望ユーザー名を登録(②が解決すればできます)

発生している問題・エラー

送れているはずの変数を、別ページで参照できません。

該当するソースコード

▼localhost/hoge/account/index.php

<?php
/*中略*/
     <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
        
     <script type="text/javascript">
          $.ajax({
               success : function(response){
               alert('ajaxの接続は成功');
               //ページを開くと毎回「ajaxの接続は成功」と出ています。
          },
               error: function(){
                    alert('ajaxの通信失敗');
               }
          });
     </script>
</head>

<body>
<main class="main">

<?php /* JavaScript用の関数定義 */ ?>
     <script type="text/javascript">
          function changeName(){
               var newName = window.prompt("新しい名前を入力してください","");

               //ajaxでphpにデータを送る
               
               let xhr = new XMLHttpRequest();
               xhr.open('POST','../experiment/',true);
               xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
               xhr.send('text='+newName);

               xhr.onreadystatechange = function(){
                    if(xhr.readyState == 4 && xhr.status == 200){
                         alert("送れました"); //これも毎回表示されます
                         location.href="../experiment/";
                    }
               }
          };

<?php /* 中略 */ ?>

     <ul>旧アカウント名が入ります<input type="button" onClick="changeName()" value="変更する"></ul>

<?php /* 後略 */ ?>

▼localhost/hoge/experiment/index.php ※実験用のphpファイル

<?php

/* 中略 */

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
        
<script type="text/javascript">
     $.ajax({
          success : function(response){
               alert('ajaxの接続は成功');
               //ページを開くと毎回「ajaxの接続は成功」と出ています。
          },
          error: function(){
               alert('ajaxの通信失敗');
          }
     });
</script>
</head>

<body>
echo var_dump($_POST);
//出力結果は「array(0) { }」になってしまう

?>
</body>

<?php /* 後略 */ ?>

備考

  • jQueryや$.postでも同じシステムを実装しようとしましたが、うまくいきませんでした。
  • ほかの方法で「window.promptの入力内容をPHPのPDO経由でSQLに登録」が実装できるようなら、そのアイデアをご教示いただければ幸いです。 ※inputタグから$_POSTにデータを格納して……という方法のほうが楽なのは承知しておりますが、技術練習のため今回はこの方法をあえて避けています。
0

4Answer

xhr.onreadystatechange = function(){
  if(xhr.readyState == 4 && xhr.status == 200){
    alert("送れました"); //これも毎回表示されます
-    location.href="../experiment/";
+    console.log(xhr.response);
  }
}

このような感じでxhr.responseのデータを確認することはできますか?

1Like

Comments

  1. @I-know-way

    Questioner

    ご回答ありがとうございます!
    ご教示のとおり、console.log(xhr.response);を行ってみました。

    --------------------------------------------
    localhost/hoge/experiment/index.phpのソースが入る)array(1){
    ["text"]=>
    string(7) "newname"
    }
    --------------------------------------------
    というように、この時点ではwindow.promptに入力した文字列(newname)がきちんと反映されているようです。
  2. その出力であれば、値は受け渡しできていそうです。
    「変数受け渡しができません」というのが「location.hrefで画面遷移したらvar_dump($_POST)の出力結果が空」というのであれば、webの通信について誤解がありそうです。

    「XMLHttpRequestでの送信(send)」と「location.hrefでの画面遷移」はそれぞれ別の通信です。
    別の通信なので送信した値などは相互に確認することはできません。
    (そもそもlocation.hrefでの画面遷移はGETリクエストなので、$_POSTは常に空なのですが)

    この2つの通信はどちらもサーバにリクエストを送り、レスポンスを受け取る点は同じです。
    「XMLHttpRequestでの送信」はレスポンスをJavaScriptで受け取って任意の処理が可能で、「location.hrefでの画面遷移」はレスポンスが画面に表示される点で違います。
    サーバーサイド(PHP)の処理はどちらも「リクエストを受け取りレスポンスを返す」という点で変わりません。
  3. @I-know-way

    Questioner

    >「変数受け渡しができません」というのが「location.hrefで画面遷移したらvar_dump($_POST)の出力結果が空」というのであれば、webの通信について誤解がありそうです。

    まさにこちらです。web通信について誤解しておりました……!
    HTTPプロトコルやXMLHttpRequestなどについて、勉強しなおしてまいります。

    重ねて、ご回答ありがとうございました!

Comments

  1. @I-know-way

    Questioner

    ありがとうございます、インストールして見てみました。

    Inspectors > Raw の項目内に「POST」がないことがわかりました……。
    「GET」しかありませんでした。


    これを見て、思い当たったことがあります。
    Chromeのコンソールを監視していたとき、なぜか
    「XHR が POST "http://localhost/hoge/experiment/" の読み込みを終了しました。」
    だけでなく
    「XHR が GET "http://localhost/hoge/experiment/" の読み込みを終了しました。」
    という記載もあったのです。

    POST通信がなんらかの理由でうまくいかず、GET通信だけ稼働しているのでしょうか……。

先に、

Fidder などのキャプチャツールを使って要求・応答を見てください。

・・・と書きましたが無反応なので少し詳しく書いておきます。

例えば、以下のように jQuery Ajax を使って JSON 文字列を data に設定して POST 送信したとします。

function apiHeroesPost() {
    var j = { Id: 6, Name: "Batman" };
    var jsonString = JSON.stringify(j);
    $.ajax({
        type: "POST",
        url: "/values",
        data: jsonString,
        contentType: "application/json; charset=utf-8",
        success: function (data) {
            $('#heroes').empty();
            $.each(data, function (key, val) {
                var str = val.id + ': ' + val.name;
                $('<li/>', { html: str }).appendTo($('#heroes'));
            });
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('#heroes').empty();
            $('#heroes').text('textStatus: ' + textStatus +
                ', errorThrown: ' + errorThrown);
        }
    });
}

その要求・応答を Fiddler で見ると以下の画像のようになります。

Fiddler.jpg

期待通り要求が出ているのが分かります。送信した JSON 文字列は赤枠で囲ったとおり正しくフォームデータとして送信されています。

応答も期待通り返ってきています。コンテンツは JSON 文字列を期待していますが、青枠で囲ったように期待通りです。

応答の JSON 文字列は JavaScript オブジェクト(連想配列)にデシリアライズされて上のコードの success に設定した function の引数 data に渡されます。それを function 内のコードで html に書きだすと以下のようになります。

result.jpg

Fiddler でなくてもブラウザの開発者ツールを使って要求・応答をキャプチャできるのでやってみてください。それをしないで議論しても「闇夜に鉄砲」という感じです。

1Like

Comments

  1. @I-know-way

    Questioner

    反応遅くなり申し訳ございません。
    また、スクリーンショット付きの丁寧なご回答ありがとうございます!

    たしかにきちんと送れていますね……。
    今後はFiddlerや開発者ツールも見ながら、検証・開発を進めていきたいと思います。
  2. 結局 Fiddler で調べるとか当方のアドバイスは何もしないで終わりにしたのでしょうか? こちらの想像の斜め上を行くことをしていたようですが・・・
  3. @I-know-way

    Questioner

    Fiddlerを実行した結果については、SurferOnWww様の
    >Fidder などのキャプチャツールを使って要求・応答を見てください。
    のご回答にコメントしております。よろしくお願いいたします。
  4. 見ても何が問題だったのか分からなかったということでしょうか? ちょっとそれは考えにくいことなのですが・・・
  5. @I-know-way

    Questioner

    下記に私の素人理解の流れを書いておきます。

    ①blue32a様のご回答のなかに、
    ------------------------------
    「XMLHttpRequestでの送信(send)」と「location.hrefでの画面遷移」はそれぞれ別の通信です。
    別の通信なので送信した値などは相互に確認することはできません。
    (そもそもlocation.hrefでの画面遷移はGETリクエストなので、$_POSTは常に空なのですが)
    ------------------------------
    とありました。


    ②SurferOnWww様のご指摘をいただき、Feddlerを試したところ、
    ページ遷移後のコンソールには「POST」の項目がなく、POST通信の内容が遷移後のexperiment/index.phpまで届いていないことが判明しました。


    この2点をもって、
    ③「location.hrefで画面遷移させるならAjaxでのPOST通信は使いにくいらしい」
    ということを学び取り、
    (ここに誤解があればぜひご指摘ください。)
    (そもそも画面遷移させるのに非同期通信を用いるのが間違いだったと気づきました。)


    いい加減ながらも
    ④「クエリを使ってGET通信にしたら偶然うまくいったから、このまま使ってしまおう」
    となったわけです。
    (ここはご容赦ください。いったんサイトをイメージどおり動かしてみたいのです。
    むろんコードの合理化や改善は少しずつ行うつもりです。)
  6. > いったんサイトをイメージどおり動かしてみたいのです。

    あなたのイメージは分かっていませんが、要するに画面遷移の話だったのですか? 話が変わってきているような気がしますけど、違います? そもそも最初の問題は表題にある、

    > XMLHttpRequestでの変数受け渡しができません

    ではなかったのですか?

    何故 Ajax が出てくるのでしょう? Ajax で画面推移って、何か見当違いの方向に進んでいるような気がしますけど

Ajax理解に対する根本的な解決ではないですが、「ほしい機能」はGET通信で実装できましたので、セルフコメントを残しておきます。
experiment/index.php側でも表示されることはチェック済みです。

▼localhost/hoge/account/index.php

//前略
xhr.onreadystatechange = function(){
   if(xhr.readyState == 4 && xhr.status == 200){
      alert("送れました");
      location.href="../experiment/index.php?newname="+encodeURIComponent(newName);
//後略

▼localhost/hoge/exmeriment/index.php

//前略
echo $_GET['newname'];
//後略
0Like

Your answer might help someone💌