概要
FuelPHPに慣れてきたので、外部APIからデータを取得する処理を書いてみたいと思います。
試しに、e-Stat の APIから国勢調査の人口集計を取得してみます。前半ではFuelPHPを使わずに、e-Stat の APIの使い方を確認していきます。
なお、取得するデータの形式はいくつか選べますが、今回はJSON形式で取得します。
環境
- FuelPHP 1.8.2
- php 5.6
準備
e-Stat の APIを使用するためには、上記のリンクからユーザ登録をして、アプリケーションIDを取得する必要があります。アプリケーションIDは、ログイン後に「マイページ」>「アプリケーションID発行」と進むと発行できます。
e-Stat API の使い方
まずは、e-Stat API の使い方を確認します。
リクエストURLの生成
APIで提供されているデータは、こちらのページからアクセスできます。
提供データ | 政府統計の総合窓口(e-Stat)−API機能
今回は、次のリンク先の表00310「年齢(各歳),男女別人口,年齢別割合,平均年齢及び年齢中位数(総数及び日本人)」を使います。
国勢調査 平成27年国勢調査 人口等基本集計(男女・年齢・配偶関係,世帯の構成,住居の状態など) | データベース | 統計データを探す | 政府統計の総合窓口
右端の「表示・ダウンロード」列の「API」を押すと、次のようにリクエストURLの雛形が生成されます。
appId=
の後に、各自で発行したアプリケーションIDを貼り付けます。また、JSON形式で取得する場合は、https://api.e-stat.go.jp/rest/2.1/app
の後に/json
を付け加えます。
https://api.e-stat.go.jp/rest/2.1/app/json/getStatsData?appId=[発行したアプリケーションID]&lang=J&statsDataId=0003149249&metaGetFlg=Y&cntGetFlg=N§ionHeaderFlg=1
これをブラウザのURL入力欄に貼り付ければAPIにリクエストを送信できますが、ちょっと待ってください。このままでは全国のデータが1歳階級別で取得しようとするため、相当なデータ量になります。
リクエストパラメータの指定
データを絞り込むため、パラメータを設定します。ドキュメントを読んでもよいですが、手っ取り早い方法があったので紹介します。
先ほど選んだ「API」ボタンの横にある「DB」ボタンを押します。「統計表・グラフ表示」のページに移りますが、次のようなメッセージが表示されていると思います。
画面表示セル数 176,400 は最大画面表示セル数 50,000 を超えました。項目の絞り込みや表示位置のページ上部(欄外)への変更を行ってください。
データ量が多くて表示できないということです。統計表表示エリアの「表示項目選択」をクリックします。
すると、現在選択されている項目が表示されます。
年齢と地域の種類が150以上あるので、データ量を減らすために絞り込みます。「項目を選択」をクリックして設定します。はじめは全選択されているので、「全解除」をしてから必要な項目を選ぶとよいです。
本記事では、年齢は3階級別のみとし、地域は大阪市だけにします。
「確定」を押すと、年齢3回級別の大阪市の人口が表示されます。
表の右上にある「API」を選択すると、同様に絞り込むためのパラメータが設定されたリクエストURLが取得できます。先ほどのように、アプリケーションIDを加えて、JSON形式の指定をします。
https://api.e-stat.go.jp/rest/2.1/app/getStatsData?cdArea=27100&cdCat02=1560%2C1760%2C1770&appId=[発行したアプリケーションID]&lang=J&statsDataId=0003149249&metaGetFlg=Y&cntGetFlg=N§ionHeaderFlg=1
大阪市を示すcdArea=27100
と、年齢の3項目を示すcdCat02=1560%2C1760%2C1770
が追加されています(%2Cはカンマをエンコーディングしたものなので、年齢を示すコードは 1560,1760,1770 の3種類です)。
このリクエストURLをブラウザのURL欄に貼り付けてリクエストすると、次のような結果が得られます(折りたたんで一部を表示しています)。
FuelPHPでコントローラからAPIリクエストを送信する
ようやく本題です。前置きが長くなったので、早速コントローラとビューのサンプルコードを載せます。
コントローラ
わかりやすくするために、パラメータは配列で設定してからhttp_build_query
で組み立てています。得られたレスポンスは配列に変換してビューに渡します。
<?php class Controller_Home extends Controller { public function action_index() { //リクエストURL $request_url = 'https://api.e-stat.go.jp/rest/3.0/app/json/getStatsData'; //リクエストパラメータ $params = array( 'cdArea' => '27100', 'cdCat02' => '1560,1760,1770', 'appId' => '[アプリケーションID]', 'lang' => 'J', 'statsDataId' => '0003149249', 'metaGetFlg' => 'Y', 'cntGetFlg' => 'N', 'sectionHeaderFlg' => '1' ); //リクエストURLにパラメータを追記 $request_url .= '?'.http_build_query($params); //Request_Curlを生成 $curl = Request::forge($request_url, 'curl'); //HTTPメソッドを指定 $curl->set_method('get'); //パラメータを設定 $curl->set_params($params); //実行 $response = $curl->execute()->response(); //レスポンスコードチェック if($response->status == 200) { //Formatクラスを利用して、JSONからPHPの配列に変換 $data = Format::forge($response->body,'json')->to_array(); $view = View::forge('index'); $view->set_global('data', $data); return $view; } } }
ビュー
コードの内容は、レスポンスの[‘GET_STATS_DATA’][‘STATISTICAL_DATA’][‘CLASS_INF’]に含まれています。データの内容は、レスポンスの[‘GET_STATS_DATA’][‘STATISTICAL_DATA’][‘DATA_INF’]に含まれています。
詳細の説明は本題から外れるので省きますが、一部の項目だけ表示するテーブルを作成しています。
<!DOCTYPE html> <htmllang="ja"> <head> <metacharset="UTF-8"> <title>Document</title> <?php echo Asset::css('style.css'); ?> </head> <body> <p>---------------------- コード表 ----------------------</p> <?php foreach($data['GET_STATS_DATA']['STATISTICAL_DATA']['CLASS_INF']['CLASS_OBJ'] as $key => $class_obj): ?> <!-- 取得したデータに複数のコードが含まれていれば表示 --> <?php if(!empty($class_obj['CLASS'][0])): ?> <?php echo $class_obj['@id'].':'.$class_obj['@name']; ?> <table> <thead> <tr> <th>@code</th> <th>@name</th> <th>@level</th> <th>@unit</th> </tr> </thead> <tbody> <?php foreach($class_obj['CLASS'] as $key => $value): ?> <tr> <td><?php if(!empty($value['@code'])){ echo $value['@code']; } ?></td> <td><?php if(!empty($value['@name'])){ echo $value['@name']; } ?></td> <td><?php if(!empty($value['@level'])){ echo $value['@level']; } ?></td> <td><?php if(!empty($value['@unit'])){ echo $value['@unit']; } ?></td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif; ?> <?php endforeach; ?> <p>---------------------- データ内容 ----------------------</p> <table> <thead> <th>@cat01</th> <th>@cat02</th> <th>@cat03</th> <th>@cat04</th> <th>@unit</th> <th>値</th> </thead> <tbody> <?php foreach($data['GET_STATS_DATA']['STATISTICAL_DATA']['DATA_INF']['VALUE'] as $key => $value): ?> <tr> <td><?php if(!empty($value['@cat01'])){ echo $value['@cat01']; } ?></td> <td><?php if(!empty($value['@cat02'])){ echo $value['@cat02']; } ?></td> <td><?php if(!empty($value['@cat03'])){ echo $value['@cat03']; } ?></td> <td><?php if(!empty($value['@cat04'])){ echo $value['@cat04']; } ?></td> <td><?php if(!empty($value['@unit'])){ echo $value['@unit']; } ?></td> <td><?php if(!empty($value['$'])){ echo $value['$']; } ?></td> </tr> <?php endforeach; ?> </tbody> </table> <?php $data['GET_STATS_DATA']['STATISTICAL_DATA']['DATA_INF']['VALUE'] ?> </body> </html>
ブラウザの出力結果
レスポンスの内容を表示できました。
感想
今回参照したデータは、全国の市町村に対して1歳階級別に用意されていたため、必要なデータを抽出するのが大変でした。データもコードによって整理されているため、視覚的にわかりやすくするにはコードの内容と結合した方がよいです。
また、本記事のようにビューで整理しようとすると面倒になるので、コントローラで整理してから表示した方がよいと思います。できたら一旦DBに格納した方が、その後の集計は楽になると思います。