生活の跡

個人的な備忘録

FuelPHPで外部APIから取得した結果がデコードされていない

概要

FuelPHPのコントローラから外部APIにアクセスしてみました。結果は取得できましたが、日本語の部分がデコードされていませんでした。例えば、「石井」なら「\u77F3\u4E95」になってる状態です。日本語でおk!

環境

  • FuelPHP 1.8.2
  • php 5.6

コントローラから外部APIのレスポンスを取得する

パラメータは省略していますが、大体こんな感じで外部API(ここではe-Stat)にリクエストしました。

<?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' => '01100',
      'cdCat02' => '1530,1540,1550,1570,1580,1590,1600,1610'
      'appId' => '****', 
    );
    
    //リクエスト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();

    //結果の確認
    echo $response;
  }
}

curlのオプションは特に設定せずにリクエストしています。最後に結果をechoで画面表示すると次のようになりました。 f:id:ishii-akihiro:20191030102325p:plain

日本語がデコードされていません。STATUSは0(正常)だけど全然よくない(笑)
curlを使わずにブラウザで直接$request_urlの内容を貼り付けてアクセスしたら日本語の結果も表示されるのに何故。。

実はちゃんと取得できていた説が浮上

調べると同じように困っている方は見つかるのですが、解決策には至らず。3時間ほど格闘してたどり着いたのがPHPではなくFileMakerの掲示板でした。

f:id:ishii-akihiro:20191030094834p:plain

[解決] APIからの返り値(Unicode文字?)の日本語変換方法 (ページ 1) / 初心者のFileMaker pro Q&A / 初心者のFileMaker pro Q&A

え?JSONならそのまま抽出したらOK?
まさかと思いましたが、$responseをそのまま出力せずに、配列に変換してから一部の要素を取り出してみます。コントローラから $response を echo する箇所は削除して、次のような処理を加えます。

〜省略〜
    //実行
    $response = $curl->execute()->response();

    //レスポンスコードチェック
    if($response->status == 200)
    {
      //Formatクラスを利用して、JSONからPHPの配列に変換
      $data = \Format::forge($response->body,'json')->to_array();

      //中身をチェック
      var_dump($data['GET_STATS_DATA']['STATISTICAL_DATA']);
    }
    
  }
}

結果はこちら。

f:id:ishii-akihiro:20191030102457p:plain 日本語も正しく表示されました。何それ!

その後の不可解な現象

夜中の0時を回っていたので一旦寝ました。翌朝にこの記事を書いているのですが、再現しようと試したら普通にecho $response;でも日本語が正しく表示されました。証拠隠滅やめろ(笑)
しばらくして、もう一度echo $response;したらデコードされずに表示されました。ブラウザの都合かな。。まあいいや。

おわりに

ひとまず生の結果を確認しようとするのは人の常だと思いますが、デコードにこだわらずに実用的な処理(配列に格納してから使用)をしていれば問題にすらならなかったと思います。似たようなことでハマったら試してみてください。

参考

FuelPHPでのcurlの使い方(外部APIへのリクエスト)は、こちらのドキュメントが参考になります。 fuelphp.jp