🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

PHP

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Ajax

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

Q&A

解決済

1回答

1175閲覧

Ajax PHP の問い合わせフォームでメールアドレスが文字化けしてしまう

VimSuke

総合スコア8

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

PHP

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Ajax

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

0グッド

0クリップ

投稿2019/11/17 01:48

前提・実現したいこと

AjaxとPHPを使って自動返信機能付きの問い合わせフォームの実装

発生している問題・エラーメッセージ

入力フォームで入力されたメールアドレスが文字化けしてPHPに渡されてしまいます。
具体的には「hoge.muni@gmail.com」 → 「hoge_muni@gmail_com」 の様にドットがアンダーバーに変換されてしまいます。
JavaScriptでJSON形式に変換するまでは問題も無さそうなのですが、PHPに渡すと文字化けします。

該当のソースコード

html

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4<meta charset="utf-8"> 5<title>AjaxMailForm</title> 6<link href="hello_ajax.css" rel="stylesheet" type="text/css"> 7</head> 8<body> 9 <h1>Hello_ajax</h1> 10 11 <table> 12 <tr> 13 <th>商品配達先ご記入欄<span class="required">*は必須項目</span></th> 14 </tr> 15 <tr> 16 <th><span class="required">*</span>氏名</th> 17 <td> 18 <label>姓:</label><input type="text" id="familyName" name="requiredItem" placeholder="例)牟尼"> 19 <label>名:</label><input type="text" id="firstName" name="requiredItem" placeholder="例)歩花"> 20 </td> 21 </tr> 22 <tr> 23 <th><span class="required">*</span>カタカナ</th> 24 <td> 25 <label>姓:</label><input type="text" id="familyKana" name="requiredItem" placeholder="例)ムニ"> 26 <label>名:</label><input type="text" id="firstKana" name="requiredItem" placeholder="例)ホゲ"> 27 </td> 28 </tr> 29 <tr> 30 <th><span class="required">*</span>メールアドレス</th> 31 <td> 32 <input type="text" id="email" size="30" placeholder="例)muni-hoge123@〇〇.co.jp"> 33 </td> 34 </tr> 35 <tr> 36 <th>配達希望時間</th> 37 <td> 38 <label>指定なし:</label><input name="deliveryTime" type="radio" value="指定なし"> 39 <label>午前中:</label><input name="deliveryTime" type="radio" value="午前中"> 40 <label>12~14時:</label><input name="deliveryTime" type="radio" value="12-14時"> 41 <label>14~16時:</label><input name="deliveryTime" type="radio" value="14-16時"> 42 <label>16~18時:</label><input name="deliveryTime" type="radio" value="16-18時"> 43 <label>18~20時:</label><input name="deliveryTime" type="radio" value="18-20時"> 44 <label>20~21時:</label><input name="deliveryTime" type="radio" value="20-21時"> 45 </td> 46 </tr> 47 </table> 48 49 <button id="modalBtn">入力内容を確認</button> 50 <div id="mask"> 51 <div id="result"> 52 <div class="result-inner"> 53 <div id="checkArea"> 54 55 </div> 56 <div class="checkBtnArea"> 57 <button id="backBtn">入力画面に戻る</button> 58 <form><input id="sendBtn" type="button" name="submit" value="送信"></form> 59 </div> 60 </div> 61 62 </div> 63 </div> 64 65<script src="hello_ajax.js"></script> 66</body> 67</html> 68

JavaScript

1 2document.addEventListener('DOMContentLoaded', function() { 3 4 // ラジオボタン取得の関数 5 var getRadioValue = function(name) { 6 var result = ''; 7 var elments = document.getElementsByName(name); 8 for (var i = 0, len = elments.length; i < len; i++) { 9 var element = elments.item(i); 10 if (element.checked) { 11 result = element.value; 12 break; 13 } 14 } 15 return result; 16 }; 17 18 var mask = document.getElementById('mask'); 19 var checkArea = document.getElementById('checkArea'); 20 21 document.getElementById('modalBtn').addEventListener('click', function() { 22 23 // 必須項目の入力チェック 24 function requiredCheck(init) { 25 var requiredItems = document.getElementsByName('requiredItem'); 26 var num = init; 27 for (var i = 0, len = requiredItems.length; i < len; i++) { 28 var requiredItem = requiredItems.item(i); 29 //再度チェック時の初期化 30 requiredItem.classList.remove('notEntered'); 31 if (requiredItem.type == 'text' || requiredItem.type == 'textarea') { 32 if (requiredItem.value == '' ) { //inputが空の場合 33 requiredItem.classList.add('notEntered'); 34 num++; 35 } 36 } 37 } 38 //クロージャを利用してローカル変数のnumを参照可能にする 39 return function() { 40 return num; 41 } 42 } 43 //未入力の個数を取得 44 var requiredNum = requiredCheck(0); 45 46 // メール正規表現チェック関数 47 function checkRegEmail(str) { 48 strValue = str.value 49 var mailCheck = new RegExp('[a-z0-9._-]+@+[a-z0-9.]+[^.]$', 'gi'); 50 if (strValue.match(mailCheck)) { //マッチした場合 51 console.log("メールアドレスの形式は正しいです"); 52 return true; 53 } else { //マッチしなかった場合 54 str.classList.add('notMatch'); 55 return false; 56 } 57 } 58 // メールチェック関数の実行 59 var resultEmail = checkRegEmail(document.getElementById('email')); 60 61 // 必須項目が全て入力 & メール正規表現が確認出来た場合 62 if (requiredNum() == 0 && resultEmail) { 63 mask.style.display = 'block'; 64 //formの値を取得 65 var familyName = document.getElementById('familyName').value; //氏名(姓) 66 var firstName = document.getElementById('firstName').value; //氏名(名) 67 var familyKana = document.getElementById('familyKana').value; //カナ(姓) 68 var firstKana = document.getElementById('firstKana').value; //カナ(名) 69 var email = document.getElementById('email').value; //メールアドレス 70 var deliveryTime = getRadioValue('deliveryTime'); //配達希望時間 71 console.log(deliveryTime); 72 //確認用のテキストノードを生成 73 document.createElement('list'); 74 var checkfamilyName = document.createTextNode(familyName); 75 //ノードを挿入 76 checkArea.appendChild(checkfamilyName); 77 78 //btnクリックで確認イベント発火 79 document.getElementById('sendBtn').addEventListener('click', function() { 80 //非同期通信の処理 81 var xhr = new XMLHttpRequest(); 82 xhr.onreadystatechange = function() { 83 if(xhr.readyState === 4) { //通信完了時の処理 84 if(xhr.status === 200) { //通信成功時の処理 85 checkArea.textContent = xhr.responseText; 86 } else { //通信が失敗した時 87 checkArea.textContent = 'サーバーエラーが発生しました。'; 88 } 89 } else { //通信が完了する前 90 checkArea.textContent = '通信中...'; 91 } 92 }; 93 //JSONデータとして格納 94 var sendData = JSON.stringify({ 95 'familyName' : familyName, 96 'firstName' : firstName, 97 'familyKana' : familyKana, 98 'firstKana' : firstKana, 99 'email' : email, 100 101 'deliveryTime' : deliveryTime 102 }); 103 //POSTメソッドでデータ送信 104 xhr.open('POST', 'hello_ajax.php', true); 105 xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8'); 106 xhr.send(sendData); 107 console.log(email) 108 }, false); 109 } 110 }, false); 111 112 //backBtnクリックで入力確認画面へ戻る 113 document.getElementById('backBtn').addEventListener('click', function() { 114 mask.style.display = 'none'; 115 }, false); 116}, false); 117 118

PHP

1<?php 2 3// 日本語対応 4mb_language("ja"); 5mb_internal_encoding("UTF-8"); 6 7// タイムゾーンの定義 8date_default_timezone_set('Asia/Tokyo'); 9 10// JSONの取扱宣言 11header( "Content-Type: application/json; charset=utf-8" ) ; 12 13//エラー表示設定 14error_reporting(E_ALL); 15ini_set('display_errors',1); 16 17 18 19//POSTで受けとったJSONデータをオブジェクトデータに変更 20$i = 0; 21$arr = []; 22foreach($_POST as $key => $value) { 23 $i++; 24 $obj = json_decode($key); 25} 26function h($value) { 27 return htmlspecialchars($value,ENT_QUOTES,'UTF-8'); 28} 29 30//各フォームの変数定義 31$familyName = h($obj->familyName); //氏名(姓) 32$firstName = h($obj->firstName); //氏名(名) 33$familyKana = h($obj->familyKana); //カナ(姓) 34$firstKana = h($obj->firstKana); //カナ(名) 35$email = h($obj->email); //メールアドレス(自動返信) 36 37$deliveryTime = h($obj->deliveryTime); //配達希望時間 38 39 40 41$name = "お客様名前"; 42 43 44$contentbox = '本文'; 45 46 47$fromEmail = "Web管理者のメールアドレス"; 48$fromName = "Web管理者の名前"; 49 50 51 52//自動返信メールの内容 53$subject = "この度はお問い合わせいただきありがとうございました。"; 54 55//メール本文 56$body = <<< EOM 57{$name}58 59お問い合わせいただきありがとうございます。 60以下の内容で受け付けいたしました。 61 62=================================================== 63 64お名前:{$familyName} {$firstName} 65カタカナ:{$familyKana} {$firstKana} 66メール:$email 67 68配達希望時間:{$deliveryTime} 69 70お問い合わせ内容:{$contentbox} 71 72=================================================== 73 74担当者よりご連絡いたしますので今しばらくお待ちくださいませ。 75 76EOM; 77 78 79//Web管理者への確認メール 80$subbody = <<< EOM 81 82Webサイトからお問い合わせいただきました。 83以下に内容を記載しています。 84 85=================================================== 86【 お名前 】 87{$familyName} {$firstName} 88【 カタカナ 】 89{$familyKana} {$firstKana} 90 91【 メール 】 92 93【 配達希望時間 】 94{$deliveryTime} 95 96【 お問い合わせ内容 】 97{$contentbox} 98=================================================== 99EOM; 100 101 102//ヘッダー情報の設定(自動返信) 103$header = ''; 104$header .= "Content-Type: text/plain \r\n"; 105$header .= "Return-Path: " . $fromEmail . " \r\n"; 106$header .= "From: " . mb_encode_mimeheader($fromName) ."<{$fromEmail}> \r\n"; 107$header .= "Sender: " . $fromName ." \r\n"; 108$header .= "Reply-To: " . $fromEmail . " \r\n"; 109$header .= "Organization: " . $fromEmail . " \r\n"; 110$header .= "X-Sender: " . $fromEmail . " \r\n"; 111$header .= "X-Priority: 3 \r\n"; 112$param = "-f" . $fromEmail; 113 114//ヘッダー情報の設定(Web管理者) 115$subheader = ''; 116$subheader .= "Content-Type: text/plain \r\n"; 117$subheader .= "Return-Path: " . $email . " \r\n"; 118$subheader .= "From: " . mb_encode_mimeheader($name) ."<{$email}> \r\n"; 119$subheader .= "Sender: " . $name ." \r\n"; 120$subheader .= "Reply-To: " . $email . " \r\n"; 121$subheader .= "Organization: " . $email . " \r\n"; 122$subheader .= "X-Sender: " . $email . " \r\n"; 123$subheader .= "X-Priority: 3 \r\n"; 124$subparam = "-f" . $email; 125 126//送信者へメール送信(自動返信) 127mb_send_mail($email, $subject, $body, $header, $param); 128 129//メール送信(Web管理者) 130mb_send_mail($fromEmail, $subject, $subbody, $subheader, $subparam); 131 132 133// 完了画面に表示される内容 134print($body); 135 136 137 138 139 140 141?> 142

試したこと

JavaScript

1xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');

この部分をJSONで渡すので、「application/json」にしてみたり

JavaScript

1xhr.setRequestHeader('Content-Type','application/json; charset=UTF-8');

PHP側で
json_decode()やらjson_encode()など色々試してみみましたが何故か文字化けしてしまいます。困り果てております。

補足情報(FW/ツールのバージョンなど)

環境
レンタルサーバーで PHP 7.3.9 (CGI版) です。
不完全な部分が多々あると思いますが、どうぞよろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2019/11/17 02:29 編集

起きている現象は文字化けとは違います。ただ、変数名やキー(name)ならともかく値が変換されるのはあまり聞かないですね。 https://www.php.net/manual/ja/language.variables.external.php >注意: 変数名のドットやスペースはアンダースコアに変換されます。 たとえば <input name="a.b" /> は $_REQUEST["a_b"] となります。 最小構成(ミニマム)のコードも試してみてください。 1項目しか授受しない、余計な処理は挟まない ような内容で
VimSuke

2019/11/17 14:42

ご丁寧な助言ありがとうございます。最小構成で何度もテストを繰り返し解決しました。 取得時に、$_POSTではなく file_get_contents( 'php://input' ); で取得するのが正しい様でした。 ありがとうございました!!
m.ts10806

2019/11/17 23:02

普通に$_POSTで受け取れますが…
VimSuke

2019/11/17 23:44

??どこかの記事でJSONデータを受け取る場合$_POSTだと中身が空(null?)になると書いてあって(あやふやな記憶ですがそれっぽいこと書いてました)その様な現象が確認されました。当コードで何か別のバグがおきているのでしょうか...引き続き1つ1つ調べて理解していきます。 ありがとうございます!
m.ts10806

2019/11/17 23:55

んーひとまず「文字化けではない」というところを認識してもらえたらなと。JSONもPHPからしたら文字列の集合体ですし、もし関係するとしたらサーバー側の仕様かなとも思います
guest

回答1

0

自己解決

取得時に、$_POSTではなく file_get_contents( 'php://input' ); で取得するのが正しい様でした。
無事に解決しました。

投稿2019/11/17 14:43

VimSuke

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問