PHPファイルの文字コードが "Shift JIS" の環境で作成していました。
<?php
//〜PHPの処理色々省略〜
?>
<!-- HTMLの記載色々省略 -->
<form method="post">
<div id="main">
<div id="search_item_box">
<div id="search_item_num_0" data-num="0">
商品カテゴリ選択:
<!-- name="item_cate[]"とすることで配列入力を配列型にすることができる -->
<label><input type="radio" name="item_cate[0]" value="none" checked>なし</label >
<label><input type="radio" name="item_cate[0]" value="product">食材</label >
<label><input type="radio" name="item_cate[0]" value="product_tokubai">特売(食材)</label >
<label><input type="radio" name="item_cate[0]" value="product_b">食材以外</label >
<label><input type="radio" name="item_cate[0]" value="product_b_tokubai">特売(食材以外)</label >
<label><input type="radio" name="item_cate[0]" value="product_new">新登録商品(食材)</label >
<label><input type="radio" name="item_cate[0]" value="product_b_new">新登録商品(食材以外)</label >
<div>
品番シリアル:
<input type="text" name="dat_serial[0]" value="">
<button type="button" onclick="item_remove('search_item_num_0')"><i class="fas fa-times"></i></button>
</div>
</div>
</div>
<div>
<button type="button" onclick="asynchronous_btn(this.form, 'search')">非同期検索</button>
<!-- このボタンを押すと非同期通信が発生 -->
<button type="button" onclick="item_addition()"><i class="fas fa-plus"></i></button>
<!-- このボタンを押すと入力欄が増える -->
</div>
<div id="search_item_display">
<!-- ここに検索結果が表示される -->
</div>
</div>
</form>
<script>
// 商品検索欄追加
let searchNum = 0;
function item_addition(){
searchNum++;
let searchItem = `<div id="search_item_num_${searchNum}" data-num="${searchNum}">
商品カテゴリ選択:
<label><input type="radio" name="item_cate[${searchNum}]" value="none" checked>なし</label >
<label><input type="radio" name="item_cate[${searchNum}]" value="product">食材</label >
<label><input type="radio" name="item_cate[${searchNum}]" value="product_tokubai">特売(食材)</label >
<label><input type="radio" name="item_cate[${searchNum}]" value="product_r">ロイヤルキッチン</label >
<label><input type="radio" name="item_cate[${searchNum}]" value="product_b">食材以外</label >
<label><input type="radio" name="item_cate[${searchNum}]" value="product_b_tokubai">特売(食材以外)</label >
<label><input type="radio" name="item_cate[${searchNum}]" value="product_gift">ギフト食材</label >
<label><input type="radio" name="item_cate[${searchNum}]" value="product_new">新登録商品(食材)</label >
<label><input type="radio" name="item_cate[${searchNum}]" value="product_b_new">新登録商品(食材以外)</label >
<div>
品番シリアル:
<input type="text" name="dat_serial[${searchNum}]" class="to_check" value="">
<button type="button" onclick="item_remove('search_item_num_${searchNum}')"><i class="fas fa-times"></i></button>
</div>
</div>`;
const target = document.getElementById('search_item_box');
target.insertAdjacentHTML('beforeend', searchItem);
}
// 商品検索欄削除
function item_remove(searchItemNum){
const removeTarget = document.getElementById(`${searchItemNum}`);
removeTarget.remove();
}
// 非同期検索
function asynchronous_btn(form) {
let displayTarget = '';
let item_cate_arr=[];
let dat_serial_arr=[];
let searchItems = document.getElementById('search_item_box');
// search_item_boxのidの要素を取得
let itemSearchCount = searchItems.childElementCount;
// searchItemsの子要素の数を数える
// formの配列をJSの配列に転換
for (let i = 0; i < itemSearchCount; i++) {
let searchItemDataset = searchItems.children[i].dataset.num;
// searchItemsのi番目の子要素のデータ属性の値を取得
item_cate_arr.push(form.elements[`item_cate[${searchItemDataset}]`].value)
// formのname属性がitem_cate[]の値を一つずつ取り出し、JSの配列に入れる
dat_serial_arr.push(form.elements[`dat_serial[${searchItemDataset}]`].value)
// formのname属性がdat_serial[]の値を一つずつ取り出し、JSの配列に入れる
}
// 送信処理
fetch('./asynchronous_search.php',{// 送信先
method:'POST',// 送信メソッド
body: new URLSearchParams({// 送信する値
item_cate : JSON.stringify(item_cate_arr),
dat_serial : JSON.stringify(dat_serial_arr),
// JSON.stringify()でJSON形式にエンコードすることで、「文字列化」して送信できるようにする
})
})// ここでasynchronous_search.phpに送信される
// asynchronous_search.phpから結果が返ってくる
.then(response => response.json())//JSON形式できちんと返ってきているかの確認(値は.thenの引数に入る)
.then(data => {//成功時の処理(値は.thenの引数に入る)
displayTarget = document.getElementById('search_item_display');
displayTarget.innerHTML = data;
// displayTargetの子要素として返ってきた値を設置(HTML形式で返すようにしている)
})
.catch(error => {
// ネットワークエラーでも !response.ok でもここで処理できる
console.error('エラーが発生しました', error);
});
}
</script>
asynchronous_search.php
<?php
//送信された値を受け取る
$p_item_cate_arr = '';
isset($_POST['item_cate']) && $p_item_cate_arr = json_decode($_POST['item_cate']);
$p_dat_serial_arr = '';
isset($_POST['dat_serial']) && $p_dat_serial_arr = json_decode($_POST['dat_serial']);
//////////////////////////////////////////////////////////////////////
// $search_result = DBから該当のデータを取得(省略)
//////////////////////////////////////////////////////////////////////
//商品検索結果表示
$search_result_disp = '';
if($search_result){
if(empty($search_result)){
$search_result_disp .= '<p><font color="red">対象商品が見つかりません。</font></p>';
}else{
$search_result_disp .= '<table border="1" style="border-collapse: collapse">
<tr>
<th>品番</th>
<th>商品名</th>
<th>単価</th>
</tr>
';
foreach($search_result as $item_dat){
$search_result_disp .= sprintf('<tr>
<td>%1$s</td>
<td>%2$s</td>
<td>%3$s円</td>
</tr>
'
,$item_dat['dat_serial']
,$item_dat['dat_item']
,number_format($item_dat['unit_price'])
);
}
$search_result_disp .= '</table>';
}
}
mb_convert_variables("utf-8","sjis",$search_result_disp);
//文字コードをsjisからutf-8にエンコード
header('Content-Type: application/json; charset=utf-8');
//送り返すデータのタイプを宣言・文字コードも宣言
echo json_encode($search_result_disp);
//JSON型にエンコードして送り返す
//(PHPのjson_encodeでは文字コードがutf-8になるらしい。その為先にutf-8に変換しておかないとエラーになる)
exit;
// 処理を切る為