【Laravel】GoogleMapsAPIで住所から緯度経度を取得する方法

2020/10/17に公開

はじめに

この記事のゴール

Laravelのプロジェクト内で、住所から緯度経度を取得します

この記事の続きです。
【Laravel】GoogleMapsAPIを使って現在地を表示させる方法

【完成の図】

ゴールまでの道のり

  1. ジオコーディングのAPIを有効にする
  2. フォームの記述
  3. jsファイルの作成

この記事の対象者

  • 初めてGoogleMapsAPIを使う方
  • Laravel初学者

環境

  • macOS Catalina 10.15.5
  • PHP 7.3.17
  • Laravel Framework 6.18.41

実践

1. ジオコーディングのAPIを有効にする

GoogleAPIsのこのプロジェクトのダッシュボードへ移動します。

「APIとサービスの有効化」をクリックします。


左下の「マップ」をクリック


「Geocoding API」をクリック


「有効にする」をクリック(自分の場合は、もう既に有効にしてしまっているので「APIが有効です」と表示されています)

これで、ジオコーディングのAPIを有効にすることができました。

2. フォームの記述

次に、住所から緯度経度を取得する際に必要なフォームを作成していきます。

まず、前回( 【Laravel】GoogleMapsAPIを使って現在地を表示させる方法)までで、resources/views/welcome.blade.phpは

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
    省略
    </head>
   <body>
    <div id="map" style="height:500px">
    </div>
    {!! Form::open(['route' => 'result.currentLocation','method' => 'get']) !!}
    {{--隠しフォームでlivescontrollerに位置情報を渡す--}}
    {{--lat用--}}
    {!! Form::hidden('lat','lat',['class'=>'lat_input']) !!}
    {{--lng用--}}
    {!! Form::hidden('lng','lng',['class'=>'lng_input']) !!}
    {{--setlocation.jsを読み込んで、位置情報取得するまで押せないようにdisabledを付与し、非アクティブにする。--}}
    {{--その後、disableはfalseになるようにsetlocation.js内に記述した--}}
    {!! Form::submit("周辺を表示", ['class' => "btn btn-success btn-block",'disabled']) !!}
    {!! Form::close() !!}

    <script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
    <script src="{{ asset('/js/setLocation.js') }}"></script>
    <script src="{{ asset('/js/result.js') }}"></script>
    <script src="https://maps.googleapis.com/maps/api/js?language=ja&region=JP&key=AIzaSyDkveHRqHWUqMU4CS_isfGbuBrzzoo6v4o&callback=initMap" async defer>
    </script>
    </body>
</html>

このようになっていると思います。
この章では、

  • 住所を入力するinputタグ
  • 住所を緯度経度へ変換するボタンタグ
  • 住所から変換された緯度経度を表示するinputタグ
  • JSファイルの読み込み設定

この、3つのタグを作成 + jsファイルを読み込むための記述をしていきます。

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
    省略
    </head>
   <body>
    <div id="map" style="height:500px">
    </div>
    {!! Form::open(['route' => 'result.currentLocation','method' => 'get']) !!}
    {{--隠しフォームでlivescontrollerに位置情報を渡す--}}
    {{--lat用--}}
    {!! Form::hidden('lat','lat',['class'=>'lat_input']) !!}
    {{--lng用--}}
    {!! Form::hidden('lng','lng',['class'=>'lng_input']) !!}
    {{--setlocation.jsを読み込んで、位置情報取得するまで押せないようにdisabledを付与し、非アクティブにする。--}}
    {{--その後、disableはfalseになるようにsetlocation.js内に記述した--}}
    {!! Form::submit("周辺を表示", ['class' => "btn btn-success btn-block",'disabled']) !!}
    {!! Form::close() !!}
    
    //ここから下を追加
    
    <input type="text" id="addressInput">
    <button id="searchGeo">緯度経度変換</button>
    <div>
        緯度:<input type="text" id="lat">
        経度:<input type="text" id="lng">
    </div>
    
    //ここから上を追加
    <script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
    <script src="{{ asset('/js/setLocation.js') }}"></script>
    <script src="{{ asset('/js/result.js') }}"></script>
    <script src="{{ asset('/js/getLatLng.js') }}"></script> //これを追加
    <script src="https://maps.googleapis.com/maps/api/js?language=ja&region=JP&key=AIzaSyDkveHRqHWUqMU4CS_isfGbuBrzzoo6v4o&callback=initMap" async defer>
    </script>
    </body>
</html>
  • <input type="text" id="addressInput">
    ここに住所を入力します。typeはtextを指定。idは、後からJSファイルで使いやすいように、addressInputを指定しています。

  • <button id="searchGeo">緯度経度変換</button>
    住所から緯度経度を取得するとき用のボタンを作成します。idはsearchGeoを指定して、ボタンの表示は「緯度経度変換」とします。

  • 緯度:<input type="text" id="lat">(経度:<input type="text" id="lng">)
    住所から取得された緯度経度をここに表示させます。typeはtextでidはlat(lng)を指定しています。

ここで一旦ブラウザを見てみましょう。

このようにフォームが作成されていると思います。

3. jsファイルの作成

最後にwelcome.blade.phpで読み込み設定をしたgetLatLng.jsを作成していきます。
public/js 内にgetLatLng.jsを作成し、以下のように記述します。

function getLatLng() {

    // 入力した住所を取得します。
    var addressInput = document.getElementById('addressInput').value;

    // Google Maps APIのジオコーダを使います。
    var geocoder = new google.maps.Geocoder();

    // ジオコーダのgeocodeを実行します。
    // 第1引数のリクエストパラメータにaddressプロパティを設定します。
    // 第2引数はコールバック関数です。取得結果を処理します。
    geocoder.geocode(
        {
            address: addressInput
        },
        function (results, status) {

            console.log(results, status)

            var latlng = "";

            if (status == google.maps.GeocoderStatus.OK) {
                // 取得が成功した場合
                // 結果をループして取得します。
                for (var i in results) {
                    if (results[i].geometry) {

                        // 緯度を取得します。
                        var lat = results[i].geometry.location.lat();
                        // 経度を取得します。
                        var lng = results[i].geometry.location.lng();

                        // val()メソッドを使ってvalue値を設定できる
                        // idがlat(またはlng)のvalue値に、変数lat(またはlng)を設定する
                        $('#lat').val(lat);
                        $('#lng').val(lng);

                        // そもそも、ループを回して、検索結果にあっているものをiに入れていっているため
                        // 精度の低いものもでてきてしまう。その必要はないから、一回でbreak
                        break;
                    }
                }
            } else if (status == google.maps.GeocoderStatus.ZERO_RESULTS) {
                alert("住所が見つかりませんでした。");
            } else if (status == google.maps.GeocoderStatus.ERROR) {
                alert("サーバ接続に失敗しました。");
            } else if (status == google.maps.GeocoderStatus.INVALID_REQUEST) {
                alert("リクエストが無効でした。");
            } else if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
                alert("リクエストの制限回数を超えました。");
            } else if (status == google.maps.GeocoderStatus.REQUEST_DENIED) {
                alert("サービスが使えない状態でした。");
            } else if (status == google.maps.GeocoderStatus.UNKNOWN_ERROR) {
                alert("原因不明のエラーが発生しました。");
            }
        });
}
$('#searchGeo').on('click', getLatLng);

ポイントは3つです。
1 var addressInput = document.getElementById('addressInput').value;これを記述することで、welcome.blade.php内のidがaddressInputの、value属性を変数addressInputに格納しています。
2 var geocoder = new google.maps.Geocoder();この記述でGeocoderをインスタンス化しています。
3 geocoder.geocode()とすることで、geocoderを実行します。第一引数には、addressプロパティを設定し、入力した住所を格納しているaddressInputを指定します。第二引数には、コールバック関数を設定しています。住所の取得結果を用いて取得成功の場合は、緯度(経度)を取得し、idがlat(lng)のvalue属性に格納しています。また、住所の取得結果に失敗した場合は、ステータスに応じてその結果を表示させるようにelseifで記述しています。

さて、ここまで来ると完成です。
ブラウザで確認してみましょう。

住所を入力し、緯度経度変換ボタンを押せば、緯度経度が表示されてます。

以上が
「GoogleMapsAPIで住所から緯度経度を取得する方法」でした。

おわりに

以上で、地図3部作のすべてが終了しました。
見ていただきありがとうございました。

Discussion