wordfes_title

2014.8.29 日に開催された WordFes に、今年も実行員とセッションスピーカーとして参加させていただきました。

2014_wordfes
写真:よつばデザインの後藤さん

その内容として、「外部APIとの連携」という事で、僕がお城好きという事で作ったGPSスタンプラリー「戦国攻城記」で使っている位置情報連携部分の一部を紹介しました。

スポンサーリンク

技術系セッション難しい・・・

既に存在してるソースを貼って解説すればいいからそんなに負荷は高くないかなと思っていたのですが大間違い。
いざ見なおしてみると、自分が理解してなくて解説出来なかったり、欠陥があって改善してからでないととても公開出来なかったりで、そもそも題材にするソースを用意するのに時間がかかってしまいました。

あとは、ソースの解説ばかりなので、わかりやすく解説しないと、「意味が理解出来ない数学の授業」状態になってしまい、聞く人が眠くなるので、何とか眠くならないようにするのに気を使いました。。。

ただ、かなりしんどかったのですが、やはりこういった場に登壇すると、いろいろと新しい技術的な発見も多々あり、やってよかったなと思います。

今回参加出来なかった方も、来月にはWordCampTokyoがありますので、是非参加してみてください。

WordPressとGeolocationAPIの連携の資料

連携方法や解説はスライドにほぼ書いてあり、サンプルソースも貼ってあるのですが、何分PowePointに貼ってPDF化しているので、ソースをコピペしても部分的に全角になったりして動かないかもしれないので、こちらに貼り直しておきます。

GeolocationAPIとWordPressの連携 (1)

位置情報を取得するjs

※別途jQueryを読み込んでいる事が前提です。
※外部jsファイルに記述して読み込みます。

/*-------------------------------------------*/
/*  位置情報取得
/*-------------------------------------------*/
jQuery(document).ready(function(jQuery){
    function get_gps(){
        if (navigator.geolocation) {
            // Geolocationが使える場合
            // 現在の位置情報を取得
            navigator.geolocation.getCurrentPosition(
                // (1)位置情報取得に成功したとき
                function (position) {
                        lat= position.coords.latitude;
                        lng= position.coords.longitude;
                        location.href=" /nearby/?lat=" + lat + "&lng=" + lng;
                },
                // (2)位置情報の取得に失敗した場合
                function (error) {
                    window.alert("位置情報の取得ができませんでした。");
                } // function (error)
            );
        } else {
            // Geolocationが使えない場合
            window.alert("このブラウザでは位置情報が取得出来ないためご利用できません。");
        }
    } // get_gps
    // ボタンがクリックされたら
    jQuery('a#nearbyBtn').click(function(){
        // 位置情報取得の処理を実行
        get_gps();
    });
});

位置情報のパラメーターを受け取って近くのお城順に並べる

移動先の固定ページのテンプレートファイル(PHP)に記述

/*-------------------------------------------*/
/*  URLのパラメター(緯度と経度の位置情報)を取得
/*-------------------------------------------*/
$lat = (isset($_GET['lat'])) ? esc_html($_GET['lat']) : '';
$lng = (isset($_GET['lng'])) ? esc_html($_GET['lng']) : '';

/*-------------------------------------------*/
/*  距離チェック
/*-------------------------------------------*/
/*      現在登録されている城情報を全て取得
/*-------------------------------------------*/
$spot_items = get_posts( array(
    'post_type' => 'post',      // カスタム投稿タイプチェックイン
    'posts_per_page' => -1,     // 全件
     ) );
/*      各お城情報について、現在地からの距離を算出してデータに追加
/*-------------------------------------------*/
foreach ($spot_items as $key => $spot_item) {
    $spotLat = get_post_meta($spot_item->ID,'Map_lat',true);
    $spotLng = get_post_meta($spot_item->ID,'Map_lng',true);
    if (($spotLat) && ($spotLng)) {
        $distanceLat = $spotLat - $lat;
        $distanceLng = $spotLng - $lng;
        // 距離の算出 pow = 乗算 / sqrt = 平方根
        $distance = sqrt(pow( $distanceLat ,2) + pow( $distanceLng ,2));
        // 並び替え用の数値として距離「distance」を追加
        $spot_items[$key]->distance = $distance;
    }
}
/*      距離で並び替えるという比較関数を定義
/*-------------------------------------------*/
function itemsort_by_distance( $a , $b){
  //距離を比較
  $spot_items = strcmp( $a->distance , $b->distance );
  return $spot_items;
}
/*      比較関数にそって並び替え
/*-------------------------------------------*/
usort( $spot_items , "itemsort_by_distance" );

/*-------------------------------------------*/
/*  並び替えた城情報を出力
/*-------------------------------------------*/

foreach ($spot_items as $key => $post) {
    the_title();
    echo '<br />';
}
wp_reset_postdata();

GeolocationAPIとWordPressの連携 (2)

近くにいるかの判定用処理

※スポットの詳細ページのPHPに記述
※別途 jQuery cookie の読み込みが必要です

<div id="message"></div>
<div class="sectionFrame" id="checkinSection">
<?php if ( is_user_logged_in() == TRUE ) { ?>
    <p class="center">
        <a href="#" id="checkinBtn">
        攻略の狼煙を上げる!(現地でGPSチェックイン)
        </a>
    </p>
<?php } else { ?>
    ( ログインしていない時の表示 )
<?php } ?>
</div>
<script type="text/javascript">
jQuery(document).ready(function($){
    // チェックイン処理開始
    jQuery('#checkinBtn').click(function(){
        if (navigator.geolocation) {
            // Geolocationが使える場合
            // 現在の位置情報を取得
            navigator.geolocation.getCurrentPosition(
                // (1)位置情報取得に成功したとき
                function (position) {
                        lat= position.coords.latitude;
                        lng= position.coords.longitude;
                        // お城の位置情報をカスタムフィールドから取得して判定合格エリアの座標生成
                        latMax = <?php echo esc_html(post_custom("Map_lat")) ?> + 0.015;
                        latMin = <?php echo esc_html(post_custom("Map_lat")) ?> - 0.015;
                        lngMax = <?php echo esc_html(post_custom("Map_lng")) ?> + 0.015;
                        lngMin = <?php echo esc_html(post_custom("Map_lng")) ?> - 0.015;
                        // チェックインの判定処理
                        if ( ( latMax > lat ) && ( lat > latMin ) && ( lngMax > lng ) && ( lng > lngMin ) ) {
                            // 判定OKの場合 チェックインしたお城IDをcookieに保存
                            jQuery.cookie("checkinSpotID", "<?php the_ID(); ?>",{ expires: 1 , path: '/page-checkin_post/' });
                            // チェックイン成功ページへ移動
                            location.href="<?php echo site_url(); ?>/page-checkin_post/";
                        } else {
                            // 判定失敗
                            jQuery("#message").html('離れている場合に表示するメッセージ');
                        }
                        // 判定ここまで
                },
                // (2)位置情報の取得に失敗した場合
                function (error) {
                    window.alert("位置情報の取得ができませんでした。");
                } // function (error)
            );
        } else {
            // Geolocationが使えない場合
            window.alert("このブラウザでは位置情報が取得出来ないためご利用できません。");
        }
    });
});
</script>

チェックイン成功時にチェックインデータを保存

チェックイン判定が成功だった場合に、移動先の固定ページ用phpファイルに記述

// ユーザー情報を取得
global $user_ID;
get_currentuserinfo();

// クッキーからチェックインした城のIDを取得
if(isset($_COOKIE["checkinSpotID"])) {
  $checkInId = $_COOKIE["checkinSpotID"];
}

/*-------------------------------------------*/
/*  重複チェック
/*-------------------------------------------*/
/*    今日の同じ城でのチェックイン情報を取得
/*-------------------------------------------*/
$args = array(
  'post_type' => 'checkin',   // カスタム投稿タイプチェックイン
  'orderby' => 'date',      // 日付で並び替え
  'order' => 'DESC',        // 新着順
  'posts_per_page' => 1,      // 1件のみ(最新だけで良いので)
  'author' => $user_ID,     // 現在のログインユーザー
  'meta_query' => array(      // カスタムフィールドの絞り込み条件
      array(
      'key'=>'checkin_spot_id',
      'value'=>$checkInId   // 今回のチェックインIDと同じ城番号
      ),
    ),
  'date_query'=>array(
    array(
      'year'=>date_i18n( 'Y' ),
      'monthnum'=>date_i18n( 'm' ),
      'day'=>date_i18n( 'd' ),
      )
    )
);
$todayCheckinData = get_posts($args);

// 今日のGPS攻略が無い場合投稿(その他のパラメーターは余分な処理の実行を防止するため)
if ( !$todayCheckinData && isset($checkInId) && $checkInId && $user_ID ){
  /*-------------------------------------------*/
  /*  チェックイン情報を投稿
  /*-------------------------------------------*/
  // 投稿するためのデータを作成
  $checkin_post = array();
  $checkin_post['post_type'] = 'checkin';
  $checkin_post['post_status'] = 'publish';
  $checkin_post['post_title'] = get_the_title($checkInId);
  $checkin_post['post_author'] = $user_ID;

  if ($user_ID) {
    // データベースに投稿を追加
    $posted_ID = wp_insert_post( $checkin_post );
    // 今投稿したチェックインデータのカスタムフィールド「checkin_spot_id(チェックインした城のID)」に値を追加
    add_post_meta($posted_ID, 'checkin_spot_id', $checkInId);
  }
}

参考文献

この記事を書いた人

kurudriveBizVektorコア開発者
名古屋で株式会社ベクトル というウェブ制作会社をしています。
普段はWordPressを使って企業サイトなどを制作しつつ、
WordPress関連のイベントにもよく顔を出しています。
[ 著書 ]
・いちばんやさしいWordPressの教本(共著)
・現場でかならず使われているWordPressデザインのメソッド(共著)
[ 最近のWordPressコミュニティでの活動 ]
2014 WordFesNagoya 実行委員 & セッションスピーカー
2013 WordCampTokyo セッションスピーカー(パネラー)
2013 WordFesNagoya 実行委員 & セッションスピーカー
2013 WordCrabFukui セッションスピーカー

スポンサーリンク