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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

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

Q&A

1回答

2868閲覧

JSONPについて

shinoda

総合スコア75

JavaScript

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

0グッド

0クリップ

投稿2015/12/02 05:18

お世話になります。

現在、入力フォームの郵便番号検索で入力補助の機能を実装したのですが、下記にコードを記載いたしますが、郵便番号などが入ったCSVと、渡ってきた郵便番号を検索するPHPをAのサーバーに置き、入力フォームのHTML/javascript(Ajaxで郵便番号をPHPにわたす)をBのサーバーに置きたいと考えています。
このような動きにするにはJSONPにしなければいけないと思いますが、どのようにしてよいかわからず困っています。
またクロスドメインをするにあたってのセキュリティ上の懸念事項も合わせてご教授いただければ幸いです。

別件ですがpost.phpの中のコメントアウトしてある部分の「Ajax以外からのアクセスを遮断」なのですが、ここを読ませるとうまく動作しないのですが原因がわかりません。合わせてご教授いただければ幸いです。

どうぞ宜しくお願い致します。

post.html

1<!DOCTYPE html> 2<html> 3<head> 4<title>郵便番号で住所入力補助</title> 5<meta charset="utf-8"> 6<script src="js/jquery-1.11.3.min.js"></script> 7<script src="js/post.js"></script> 8<script type="text/javascript"> 9$(function(){ 10 $('#search').click( 11 function(){ 12 $.ajax({ 13 beforeSend : function(xhr) { 14 xhr.overrideMimeType("text/plain; charset=shift_jis"); 15 }, 16 type: 'get', 17 url: "post.php", 18 data: { zipcode: $('#zip').val() }, 19 }).done(function(data){ 20 if(data == ""){ 21 alert('該当する住所が見つかりませんでした。'); 22 } else { 23 $("#address").val(data); 24 } 25 }).fail(function(XMLHttpRequest, textStatus, errorThrown){ 26 alert(errorThrown); 27 }); 28 } 29 ); 30});</script> 31</head> 32<body> 33<form> 34 <p>郵便番号:<input type="text" name="zipcode" id="zip" size="8" value=""> 35 <input type="button" id="search" value="郵便番号で検索"></p> 36 <p>住所:<input size="50" type="text" name="address" id="address" value=""></p> 37</form> 38</body> 39</html>

post.php

1<?php 2require_once 'phpmylib/h.php'; 3 4$zipcode = $_GET['zipcode']; 5 6$dir = __DIR__ . '/zipcode'; 7 8/* 9// Ajax以外からのアクセスを遮断 10if(! isset($_SERVER['HTTP_X_REQUESTED_WITH']) || $_SERVER['HTTP_X_REQUESTED_WITH'] !== 'xmlhttprequest'){ 11 die("不正な呼び出しです"); 12} 13*/ 14 15$zipcode = mb_convert_kana($zipcode, 'a', 'utf-8'); 16$zipcode = str_replace(array('-','ー'),'', $zipcode); 17 18$result = array(); 19 20$file = $dir . DIRECTORY_SEPARATOR . substr($zipcode, 0, 1) . '.csv'; 21if(file_exists($file)){ 22 $spl = new SplFileObject($file); 23 while (!$spl->eof()) { 24 $columns = $spl->fgetcsv(); 25 if(isset($columns[0]) && $columns[0] == $zipcode){ 26 $result = array($columns[1], $columns[2], $columns[3]); 27 break; 28 } 29 } 30} 31 32if(!empty($result)){ 33 echo $result[0] . $result[1] . $result[2]; 34} 35 36header('Content-type: application/javascript; charset=utf-8'); 37 38

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

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

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

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

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

guest

回答1

0

郵便番号などが入ったCSVと、渡ってきた郵便番号を検索するPHPをAのサーバーに置き、入力フォームのHTML/javascript(Ajaxで郵便番号をPHPにわたす)をBのサーバーに置きたいと考えています。

こういうことでしょうか。

// csv http://a.com/zipcode.csv // zipコード検索スクリプト http://a.com/search.php // 検索フォーム http://b.com/index.html // ajax http://b.com/search.js

方法論としては「"http://a.com/zipcode.php" で
"http://a.com/zipcode.csv" をパースして json を返す」のがお手軽だと思います。
IE7 を対応するなら JSONP ですが、IE8+ に対応するなら XMLHttpRequest, XDomainRequest を利用すれば対応可能です。

Re: shinoda さん

投稿2015/12/02 05:51

think49

総合スコア18164

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

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

shinoda

2015/12/02 07:37

お世話になっております。 >こういうことでしょうか。 →はい、その認識で間違いないです。 >方法論としては「"http://a.com/zipcode.php" で "http://a.com/zipcode.csv" をパースして json を返す」のがお手軽だと思います。 →php側でjsonエンコーディングしても別サーバーのjavascriptからリクエストが来るのでできないと思っていたのですが認識がおかしいですか? >IE7 を対応するなら JSONP ですが、 →IE7以前は無視でよいかと考えています。 >IE8+ に対応するなら XMLHttpRequest, XDomainRequest を利用すれば対応可能です。 →php側の頭に記述すればよろしいのでしょうか? ご提示された参考サイトを拝見しましたが私のスキルでは理解ができないため、ご教授頂けますか? 以上よろしく願い致します。
think49

2015/12/02 08:04

> php側でjsonエンコーディングしても別サーバーのjavascriptからリクエストが来るのでできないと思っていたのですが認識がおかしいですか? クロスドメイン制限は XMLHttpRequest Level 2 で回避可能ですが、そういうことではなく、検索ボタンをクリックするが度にリクエストを発生する必要はないと思いました。 始めに全てのJSONデータをJavaScriptで受け取り、配列化しておけば検索ボタンをクリックしても手元の配列データを検索するだけで済みます。 郵便番号データが膨大なサイズならば通信量節約の為に逐次検索する価値はありますが、そうでないなら初回に全て読み込んでおく方がユーザの待ち時間を減らせる点でスマートだと思います。 > php側の頭に記述すればよろしいのでしょうか? Access-Control-Allow-Origin で許可するドメインを指定してください。 PHPなら header() でヘッダを指定できます。 https://www.google.co.jp/search?ie=UTF-8&q=Access-Control-Allow-Origin%20XMLHttpRequest&oq=Access-Control-Allow-Origin%20XMLHttpRequest
shinoda

2015/12/02 12:06

お世話になっております。 >検索ボタンをクリックするが度にリクエストを発生する必要はないと思いました。 始めに全てのJSONデータをJavaScriptで受け取り、配列化しておけば検索ボタンをクリックしても手元の配列データを検索するだけで済みます。 一番最初のリクエスト(javascript→php)の時にJSONファイルで全ての郵便番号データを受け取ってしまうということでしょうか? 一番最初のリクエスト時(ユーザが郵便番号を入力)には約12万件のデータをJSONエンコードしてから、フォームに結果が反映されることになると思いますが速度的に大丈夫そうですか? そもそもユーザが郵便番号を何回も入力するということは少ないかなと思っていました。 >Access-Control-Allow-Origin で許可するドメインを指定してください。 PHPなら header() でヘッダを指定できます。 参考サイトのご提示ありがとうございます。 拝見させていただきます
think49

2015/12/02 12:41

なるほど。12万件ともなると逐次検索の方がいいかもしれませんね。
shinoda

2015/12/03 03:25

お世話になっております。 少しコードを書きなおしてJSONPの作りにしてみたのですが、クロスサイトオリジン云々のエラーが出てしまいます。 やはりPHP側でヘッダにAccess-Control-Allow-Originを入れなければ駄目なのでしょうか? 以下にコードを記載します 宜しくお願い致します ``` form.html <!DOCTYPE html> <html> <head> <title>郵便番号入力フォーム</title> <meta charset="utf-8"> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script type="text/javascript"> $(document).ready(function(){ $("#search").click(function(){ var zipcode = $.trim($('#zip').val()); $.ajax({ type: "post", url: "api.php", data: JSON.stringify(zipcode), crossDomain: false, dataType : "jsonp", scriptCharset: 'utf-8' }).done(function(data){ if(data[0] == ""){ alert('見つかりませんでした。'); } else { $('#address').val(data[0] + data[1] + data[2]); } }).fail(function(XMLHttpRequest, textStatus, errorThrown){ alert(errorThrown); }); }); }); </script> </head> <body> <form> <p><input type="text" name="zip" id="zip" size="8"> <input type="button" id="search" value="郵便番号で検索"></p> <p><input size="50" type="text" name="address" id="address"></p> </form> </body> </html> ``` ``` api.php <?php $dir = __DIR__ . '/zipcode'; /*// Ajax以外からのアクセスを遮断 $request = (string)filter_input(INPUT_SERVER, 'HTTP_X_REQUESTED_WITH'); if(strtolower($request) !== 'xmlhttprequest') exit; */ $json = file_get_contents('php://input'); $data = json_decode($json, true); file_put_contents('test.log', print_r($data, true)); $zipcode = !empty($data) ? $data : ''; $zipcode = mb_convert_kana($zipcode, 'a', 'utf-8'); $zipcode = preg_replace('/[\sー-]/', '', $zipcode); $callback = (string)filter_input(INPUT_GET, 'callback'); $callback = htmlspecialchars(strip_tags($callback)); $param = array('', '', ''); $file = $dir . DIRECTORY_SEPARATOR . substr($zipcode, 0, 1) . '.csv'; if(file_exists($file)){ $spl = new SplFileObject($file); while (!$spl->eof()) { $columns = $spl->fgetcsv(); if(isset($columns[0]) && $columns[0] == $zipcode){ $param = array($columns[1], $columns[2], $columns[3]); break; } } } header('Content-type: application/javascript; charset=utf-8'); printf("{$callback}(%s)", json_encode( $param )); ```
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問