WordPressでGoogleマップの地図を表示する方法

# はじめに
WordPressのプラグイン「Advanced Custom Fields」を使って、投稿ページにGoogle Mapの地図を埋め込む手順です。

# 事前準備
* [Advanced Custom Fields](https://ja.wordpress.org/plugins/advanced-custom-fields/)プラグインのインストール
* Googleアカウントの作成
* 課金用クレジットカードの準備
    * ※アクセス数が多くない限り無料枠で収まりますが、登録は必要です
    * 詳しい料金はhttps://cloud.google.com/maps-platform/ を参照してください

# 試した環境
* WordPress 5.0.8
* jQuery v1.10.1

# 目次

- Google Cloud Platform(GCP)での準備
    - 新規プロジェクト作成
    - 課金アカウントの作成
    - Google Map APIの有効化
    - APIキーの取得
- 管理画面で使えるようにする設定
    - `functions.php`の編集
    - 新規フィールド(Google Map)の追加
- 投稿画面で使えるようにする設定
    - jQueryコードの追加
    - `single.php`の編集
    - カスタムフィールドの表示
    - Google Map API, jQueryコードの読み込み

# 手順
## 1.Google Cloud Platform(GCP)での準備
[Google Map API](https://cloud.google.com/maps-platform/)を使うための準備をします。

### 1-1.新規プロジェクト作成
※ GCPで既にプロジェクトを追加したことがある方はスキップしてください。


<img width="921" alt="GCP新規プロジェクトの追加" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582534/527f229e-98fd-7eb3-05ad-1f4953cb4671.png">

1. [GCP コンソール](https://console.cloud.google.com/home/dashboard)にアクセスする。
2. ヘッダーメニューオレンジ枠を選択する。
3. ポップアップ画面の右上「新しいプロジェクト」を選択する。
4. 適当なプロジェクト名を入力し、作成する。


### 1-2.課金アカウントの作成
1. ハンバーガーメニュー内「お支払い」を選択する。
2. 「アカウントを作成」ボタンから画面に沿って支払い情報を追加する。

### 1-3.API認証情報の追加
1. ハンバーガーメニュー内「APIとサービス」の「認証情報」を選択する。
2. 「認証情報を作成」ボタンを押下し「APIキー」を選択する。
3. （必要があれば）API一覧に表示されている上記2で追加したAPIキーを選択し、キーの制限セクション内を設定する。

### 1-4.Google Map APIの有効化
1. ハンバーガーメニュー内「Googleマップ」を選択する(一番下の方にあります)。
2. サイドメニューの「API」を選択する。
3. その他のAPIから下記2つのAPIを選択し、「有効にする」ボタンを押下する。
    * Maps JavaScript API
    * Places API
4. 有効なAPI一覧に表示されている上記3で追加したAPIのいずれかをクリックし、認証情報タブで表示されているキーをコピーしておく（2-1.で使います）。


## 2.管理画面で使えるようにする設定
### 2-1.新規カスタムフィールド(Google Map)の追加
※Advanced Custom Fieldsの使い方は別記事を参照してください。

フィールドタイプとして、「Google Map」を選択します。
<img width="989" alt="WordPress カスタムフィールドの選択肢一覧" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582534/d0c24827-0abb-d433-ec7d-1bfa7ad142fa.png">


フィールド名(Field Name)は3-2.で使います。
<img width="678" alt="WordPress カスタムフィールドGoogleMapの追加方法" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582534/bd159b1d-1a24-fcfe-9807-7fbb6292ae9e.png">

### 2-2.functions.phpの編集
下記コードをfunctions.phpに追加する。

```
<?php
function my_setup() {
	global $global_api_key; //投稿ページでの表示の際に必要なため、グローバル変数にしています
	$global_api_key = '1.4でコピーしたキー';
}
add_action( 'after_setup_theme', 'my_setup' );

function my_acf_google_map_api( $api ){
	global $global_api_key;
	$api['key'] = $global_api_key;
	return $api;
}
add_filter('acf/fields/google_map/api', 'my_acf_google_map_api');
```

上記設定が完了すると、管理画面の投稿の編集画面で住所や施設名などで検索して場所を設定できるようになります。
※住所を検索する際、ビル名やマンション名は入れると検索候補が出てこない場合があります。
<img width="705" alt="WordPress管理画面 GoogleMapの表示" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582534/dce48b92-1774-21c7-8a1c-59b8dfa1c11e.png">


## 3.投稿画面(single.php)に表示するための設定
### 3-1.jQueryコードの追加
下記コードをjsファイルとして保存する。（[Advanced Custom Fields ドキュメント](https://www.advancedcustomfields.com/resources/google-map/)内コードを引用）
※ 本記事では`acf-map.js`として保存します。

```
(function($) {

/**
 * initMap
 *
 * Renders a Google Map onto the selected jQuery element
 *
 * @date    22/10/19
 * @since   5.8.6
 *
 * @param   jQuery $el The jQuery element.
 * @return  object The map instance.
 */
function initMap( $el ) {

    // Find marker elements within map.
    var $markers = $el.find('.marker');

    // Create gerenic map.
    var mapArgs = {
        zoom        : $el.data('zoom') || 16,
        mapTypeId   : google.maps.MapTypeId.ROADMAP
    };
    var map = new google.maps.Map( $el[0], mapArgs );

    // Add markers.
    map.markers = [];
    $markers.each(function(){
        initMarker( $(this), map );
    });

    // Center map based on markers.
    centerMap( map );

    // Return map instance.
    return map;
}

/**
 * initMarker
 *
 * Creates a marker for the given jQuery element and map.
 *
 * @date    22/10/19
 * @since   5.8.6
 *
 * @param   jQuery $el The jQuery element.
 * @param   object The map instance.
 * @return  object The marker instance.
 */
function initMarker( $marker, map ) {

    // Get position from marker.
    var lat = $marker.data('lat');
    var lng = $marker.data('lng');
    var latLng = {
        lat: parseFloat( lat ),
        lng: parseFloat( lng )
    };

    // Create marker instance.
    var marker = new google.maps.Marker({
        position : latLng,
        map: map
    });

    // Append to reference for later use.
    map.markers.push( marker );

    // If marker contains HTML, add it to an infoWindow.
    if( $marker.html() ){

        // Create info window.
        var infowindow = new google.maps.InfoWindow({
            content: $marker.html()
        });

        // Show info window when marker is clicked.
        google.maps.event.addListener(marker, 'click', function() {
            infowindow.open( map, marker );
        });
    }
}

/**
 * centerMap
 *
 * Centers the map showing all markers in view.
 *
 * @date    22/10/19
 * @since   5.8.6
 *
 * @param   object The map instance.
 * @return  void
 */
function centerMap( map ) {

    // Create map boundaries from all map markers.
    var bounds = new google.maps.LatLngBounds();
    map.markers.forEach(function( marker ){
        bounds.extend({
            lat: marker.position.lat(),
            lng: marker.position.lng()
        });
    });

    // Case: Single marker.
    if( map.markers.length == 1 ){
        map.setCenter( bounds.getCenter() );

    // Case: Multiple markers.
    } else{
        map.fitBounds( bounds );
    }
}

// Render maps on page load.
$(document).ready(function(){
    $('.acf-map').each(function(){
        var map = initMap( $(this) );
    });
});

})(jQuery);
```
### 3-2.single.phpの編集
* カスタムフィールドの表示
* 
投稿ページ(single.php)のGoogle Mapの地図を表示したい箇所に下記コードを記載する。

```
<?php 
    $googlemap = get_field('googlemap'); //get_field()内の値は、2-2.で追加したフィールドの「field_name」
?>
<div class="acf-map">
    <div class="marker" data-lat="<?php echo $googlemap['lat']; ?>" data-lng="<?php echo $googlemap['lng']; ?>"></div>
</div>

<style>
.acf-map {
	width: 100%;
	height: 450px;
	position: initial !important;
	border: #ccc solid 1px;
	margin: 20px 0;
}
//レスポンシブ対応する場合は、各自で追記してください
</style>
```

複数のマーカーの表示や詳細情報の表示などする場合は
[Advanced Custom Fields ドキュメント](https://www.advancedcustomfields.com/resources/google-map/)を参照してください。

* MapApi, jQueryコードの読み込み

```
<script src="https://maps.googleapis.com/maps/api/js?key=<?php global $global_api_key; echo $global_api_key; ?>"></script>
<script type="text/javascript" src="<?php echo get_template_directory_uri(); ?>/js/acf-map.js"></script>
//グローバル変数名、ファイル名は適宜変更してください。
```

## うまく表示されないときは...

ブラウザの開発者ツールを開いて、コンソールに表示されているエラーメッセージを見てみましょう。

例）管理画面で下記表示になった場合...
<img width="703" alt="WordPress管理画面 カスタムフォールドGoogleMapで！が複数表示されるエラー画面" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582534/7b1ffa5c-f237-93c3-e2be-0b1cced96267.png">

開発者ツールのコンソールでの表示は下記の通り

```
Google Maps JavaScript API error: InvalidKeyMapError
https://developers.google.com/maps/documentation/javascript/error-messages#invalid-key-map-error
```

下記ページで、各エラーメッセージの原因と解決法が確認できます。
https://developers.google.com/maps/documentation/javascript/error-messages