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

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

ただいまの
回答率

90.34%

JSONPについて

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 845

shinoda

score 86

お世話になります。

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

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

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

<!DOCTYPE html>
<html>
<head>
<title>郵便番号で住所入力補助</title>
<meta charset="utf-8">
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/post.js"></script>
<script type="text/javascript">
$(function(){
  $('#search').click(
    function(){
      $.ajax({
        beforeSend : function(xhr) {
        xhr.overrideMimeType("text/plain; charset=shift_jis");
        },
        type: 'get',
        url: "post.php",
        data: { zipcode: $('#zip').val() },
      }).done(function(data){
            if(data == ""){
                alert('該当する住所が見つかりませんでした。');
            } else {
                $("#address").val(data);
            }
      }).fail(function(XMLHttpRequest, textStatus, errorThrown){
            alert(errorThrown);
      });
    }
  );
});</script>
</head>
<body>
<form>
    <p>郵便番号:<input type="text" name="zipcode" id="zip" size="8" value="">
    <input type="button" id="search" value="郵便番号で検索"></p>
    <p>住所:<input size="50" type="text" name="address" id="address" value=""></p>
</form>
</body>
</html>

<?php
require_once 'phpmylib/h.php';

$zipcode = $_GET['zipcode'];

$dir = __DIR__ . '/zipcode';

/*
// Ajax以外からのアクセスを遮断
if(! isset($_SERVER['HTTP_X_REQUESTED_WITH']) || $_SERVER['HTTP_X_REQUESTED_WITH'] !== 'xmlhttprequest'){
    die("不正な呼び出しです");
}
*/

$zipcode = mb_convert_kana($zipcode, 'a', 'utf-8');
$zipcode = str_replace(array('-','ー'),'', $zipcode);
 
$result = 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){
            $result = array($columns[1], $columns[2], $columns[3]);
            break;
        }
    }
}
 
if(!empty($result)){
    echo $result[0] . $result[1] . $result[2];
}

header('Content-type: application/javascript; charset=utf-8');
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 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+ に対応するなら XMLHttpRequestXDomainRequest を利用すれば対応可能です。
XMLHttpRequest()
ドメイン間要求 (XDR) の概要

Re: shinoda さん

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/12/02 21:41

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

    キャンセル

  • 2015/12/03 12: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 ));
    ```

    キャンセル

  • 2015/12/03 22:23

    > やはりPHP側でヘッダにAccess-Control-Allow-Originを入れなければ駄目なのでしょうか?
    はい、その通りです。
    https://developer.mozilla.org/ja/docs/HTTP_access_control

    キャンセル

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

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る