PHPサイトにGoogleマップを追加する

 GoogleMapAPIを使えば、PHPによるWebサイトにGoogleマップを簡単に追加できる。

 GoogleMapAPIは、UbuntuやFedora、openSUSE用にパッケージ化されているわけではない。この記事では、64ビット版Fedora 9マシンでGoogleMapAPIのバージョン2.5を利用している。以下のコマンド群を実行すると、メインのPHPファイルがサイトからアクセス可能なディレクトリにインストールされ、残りのファイルは参照用として「/usr/local/php」に展開される。

# mkdir -p /usr/local/php
# mkdir -p /usr/local/php/site-includes
# chown root.apache /usr/local/php/site-includes
# chown root.apache /usr/local/php

# cd /usr/local/php
# tar xzvf /.../GoogleMapAPI-2.5.tar.gz
# install --mode 444 GoogleMapAPI-2.5/GoogleMapAPI.class.php /usr/local/php/site-includes

# vi /etc/php.ini
...
include_path = ".:/php/includes:/usr/local/php/site-includes"

 自前のサイトでGoogleマップを利用するには、固有のGoogle Maps APIキーが必要になる。また、GoogleMapAPIのインストール先となるWebサーバは、要求を処理するためにインターネットにアクセスできる必要がある。この点は主に、Webサーバがファイアウォールを介してインターネットにつながっている場合に重要になる。Webサーバから「http://maps.google.com/maps/geo」の80番ポートへの要求がうまく通らなければ、地図は表示できない。

 ここからは早速サイトに地図を表示する方法を紹介する。ここでお決まりのコードブロックが2つ出てくる。最初のブロックはPHPクラスのインクルード、gmapsオブジェクトの生成、Google Maps APIキーの設定を行う。2番目のブロックでは、生成したgmapsオブジェクトの各メソッドを呼び出して必要なHTMLコードおよびJavaScriptをHTMLページに配置する。特に興味深いと思われるのが、addMarkerByAddressメソッドを呼び出す部分だ。このコードを変更するなら、この部分だけでいいだろう。

# cd /var/www/html
# mkdir gmaptest
# chown root.apache gmaptest
# chmod +s gmaptest
# cd gmaptest
# vi index.php
<?php

require('GoogleMapAPI.class.php');

$map = new GoogleMapAPI('map');
$map->setAPIKey('........INSERT YOUR KEY HERE.......');

$map->addMarkerByAddress('eiffel tower, paris','Eiffel Tower','<b>One fine Sunday...</b>');

?>

<html>
<head>
  <?php $map->printHeaderJS(); ?>
  <?php $map->printMapJS(); ?>
</head>
<body onload="onLoad()">
   <table border=1>
    <tr><td>
    <?php $map->printMap(); ?>
    </td><td>
    <?php $map->printSidebar(); ?>
    </td></tr>
    </table>
</body>
</html>

gmap1_thumb.png
エッフェル塔周辺の地図

 GoogleMapAPIオブジェクトには、ほかにも便利なメソッドが数多くある。たとえばsetDSNメソッドでは、ジオコーディング(緯度経度情報の取得処理)情報のキャッシュに使われるリレーショナルデータベースの接続情報が得られる。なお、ジオコードのキャッシュを利用するにはPEAR::DBパッケージをインストールしておく必要がある。ジオコーディング・クエリの利用頻度と1日あたりの最大件数に対するGoogleの制限は非常に緩いが、同じ住所について何度も問い合わせるのであれば結果をキャッシュしておいたほうがよいだろう。

 setLookupServiceを使えば、別のプロバイダを選択してジオコードの検索を行うことができる。対応プロバイダにはYahoo!も含まれている。また、getGeocodeを使えば、地図に影響を与えずにジオコードを検索することができ、検索に成功した場合は指定した住所の緯度と経度が返ってくる。さらに、自分の利用したジオコード情報をputCacheによってデータベースのキャッシュに追加したり、geoGetCoordsでキャッシュを無視して検索を行ったりすることもできる。

 Googleマップのサイズ変更には、setWidthとsetHeightを使う。地図の表示形態を変えるメソッドとしては、地図の移動と拡大/縮小を無効にするdisableMapControls、航空写真および街路表示ボタンを非表示にするdisableTypeControls、すべてのマーカーのタイトルが表示されるサイドバーを隠すdisableSidebar、ルート案内の表示をオフにするdisableDirections、すべてのマーカーを画面内に表示するための自動ズームを無効にするdisableZoomEncompassがある。また、setMapTypeメソッドには、使用する地図の表示タイプを表す文字列(satellite、hybrid、mapのいずれか)を指定する。Googleマップ表示時のさまざまな要素を無効にできるメソッドはほかにもたくさんあるので、どんな設定が可能なのか、またその結果どのような表示になるのかを確認したうえで表示方法を決めるとよい。

 地図の拡大/縮小レベルを設定するメソッド(setZoomLevel)や最初の表示位置を設定するメソッド(adjustCenterCoords)もある。こうした位置決めに関するメソッドは、主としてマーカーを地図に追加していない場合に重要になる。マーカーを追加するメソッドとしては、先ほど紹介したaddMarkerByAddress以外にも、緯度と経度を指定してマーカーを追加するaddMarkerByCoordsが用意されている。住所あるいは緯度と経度の組を指定して地図上の2つの地点を線で結ぶには、それぞれaddPolyLineByAddress、addPolyLineByCoordsが使える。地図に表示されるマーカーのイメージを変えたければ、すべてのマーカーを変更するsetMarkerIconか個々のマーカーに作用するaddMarkerIconが使える。

 これらのメソッドの使用例として、さきほどのサンプルにあったaddMarkerByAddressブロックに以下のコードを追加してみよう。なお、2つの地点を結ぶ線は直線として描かれる。この点が気に入らないという人もいるだろう。通行可能な経路を線で示すには、以下の例にあるように、緯度と経度を指定して各線分を手作業でつなぎ合わせていく必要がある。コードの最後(省略記号の後ろの部分)では、簡単なジオコード検索を実行し、その結果をブラウザに表示している。このサンプルコードを実行したときのスクリーンショットも載せておく。

...
$map->addMarkerByAddress('eiffel tower, paris','Eiffel Tower','<b>One fine Sunday...</b>');
$map->addMarkerByAddress('louvre, paris','Louvre','<b>One fine Monday ;-p~~</b>');

$map->addPolyLineByAddress(
        'eiffel tower, paris',
        'louvre, paris',
        '#ff0000',5,75 );

$color = '#0000FF';
$weight = 3;
$opacity = 90;

$map->addPolyLineByCoords( 2.334075,48.861351, 2.321080,48.865450, $color, $weight, $opacity );
$map->addPolyLineByCoords( 2.321080,48.865450, 2.319029,48.864797, $color, $weight, $opacity );
$map->addPolyLineByCoords( 2.319029,48.864797, 2.313604,48.864712, $color, $weight, $opacity );
$map->addPolyLineByCoords( 2.313604,48.864712, 2.313335,48.862827, $color, $weight, $opacity );
$map->addPolyLineByCoords( 2.313335,48.862827, 2.309883,48.862600, $color, $weight, $opacity );
$map->addPolyLineByCoords( 2.309883,48.862600, 2.309128,48.862751, $color, $weight, $opacity );
$map->addPolyLineByCoords( 2.309128,48.862751, 2.302311,48.862639, $color, $weight, $opacity );
$map->addPolyLineByCoords( 2.302311,48.862639, 2.300746,48.859824, $color, $weight, $opacity );
$map->addPolyLineByCoords( 2.300746,48.859824, 2.297080,48.859055, $color, $weight, $opacity );
$map->addPolyLineByCoords( 2.297080,48.859055, 2.294449,48.858247, $color, $weight, $opacity );

....

<?php
        $gc = $map->geoGetCoords('eiffel tower, paris');
        $lat = $gc['lat']; $long = $gc['lon'];
        echo "Eiffel Tower lat: $lat long: $long";

?>
</body>
</html>

gmap2_thumb.png
サンプルコードによる表示マップ

 厄介なのは、手作業で2つの地点を線でつないでいく際に、線分ごとにaddPolyLineByCoordsを使わないといけない点だ。addPolyLineByCoordsの呼び出しを繰り返すと、終点として指定した座標が次の呼び出しの始点と重複して煩わしいので、各地点の緯度と経度の座標を配列として渡せたほうがよい。

 GoogleMapAPIはLGPLの元で配布されており、自由に利用できる。わかりやすいプログラマ向けドキュメントが用意されており、またSmartyテンプレートとも統合されているのでWebページのデザインと機能をきちんと分けておくことができる。

Ben Martinは10年以上もファイルシステムに携わっている。博士号を持ち、現在はlibferris、各種ファイルシステム、検索ソリューションを中心としたコンサルティングサービスを手がけている。

Linux.com 原文