コーディングブログ

Coding Blog

これを見れば実装できる!PHPで無料のAPI『OpenWeatherMap』を使って天気予報サイト構築を解説

API

PHP

今回実際に作成したのがこちら!
5日間の3時間天気予報

このページの仕様は、

  • 現在の天気を表示
  • 5日間の天気を表示
  • 表示する都道府県をユーザーが選択し、動的に変更する
  • 現在の天気はSVGアニメーションで動かしてみる

です。
今回はこれベースに解説していきます。

    OpenWeatherMapで出来ること

    OpenWeatherMap プラン
    https://openweathermap.org/price

    様々な有料プランがありますが、無料でも十分天気予報サイトが作れそうです。
    1分あたりの呼び出し回数に制限がありますが、趣味レベルで作る程度なら全く問題ないでしょう。

    その中で今回は、

    • 現在の天気
    • 5日間の3時間予報

    を同時に実装していきたいと思います!

    まずはAPI keyを取得

    APIを利用するためにまずはアカウントを登録して、API keyを取得する必要があります。

    API keyを取得するのはとても簡単です。
    ユーザー名、メールアドレス、パスワードと必要なチェックボックスをチェックするだけで、すぐ登録できます。

    下記リンクから登録画面へ遷移できます。
    https://home.openweathermap.org/users/sign_up

    その後、ログイン画面から ① 『API keys』へ移動し、②の『Key』からコピーしてください。

    openweathermap API key取得

    早速リクエストを送り、情報を取得する

    ここからプログラミングに入ります。

    まずはレスポンスが返ってくるか試しましょう。
    5日間の3時間天気情報を取得します。

    ▼ 公式ドキュメント
    https://openweathermap.org/forecast5

    情報を取得する関数を作りました。
    jsonを取得して、PHPで扱えるように連想配列にします。

    これでとりあえず取得できたはずです。

    ベースURL

    ベースのURLは『https://api.openweathermap.org/data/2.5/』で決まりです。
    その後にAPI Keyなどのパラメーターを付けてリクエストを送ります。

    何の情報を取得するか

    ベースURLの直後にURLに含めます。

    • 現在の天気 ⇒ weather
    • 5日間の3時間予報 ⇒ forecast

    ユーザー定義関数getWeather()の第一引数でforecastを指定します。

    どの都市の情報を取得するか

    手法としては、都市名、都市ID、座標、郵便番号で取得できます。

    種類記法
    都市名?q={都市名},{国コード}【ベースURL】/forecast?q=London,us
    都市ID?id={都市ID}【ベースURL】/forecast?id=524901
    地理座標?lat={緯度}&lon={経度}【ベースURL】/forecast?lat=35&lon=139
    郵便番号?zip={郵便番号},{国コード}【ベースURL】/forecast?zip=94040,us

    IDがユニークな値で、使いやすそうなので今回はIDで取得することにします。

    都市IDを取得

    まずはトップページの検索ボックスから表示したい都市名を英語で入力して検索します。

    OpenWeatherMap 都市検索
    https://openweathermap.org/

    そして、出てきた詳細ページのURLからIDがわかります。
    アドレスバーからIDをコピります。

    OpenWeatherMap 都市IDはこれ

    サンプルでは『shinjuku』と入力して出てきた、東京都のページです。
    東京都のIDは1850144ということが分かったので、これをユーザー定義関数getWeather()の第二引数で指定します。

    受け取ったデータ

    こんな感じの連想配列を受け取れます。

    array(5) { [“cod”]=> string(3) “200” [“message”]=> float(0.009) [“cnt”]=> int(40) [“list”]=> array(40) { [0]=> array(8) { [“dt”]=> int(1571454000) [“main”]=> array(8) { [“temp”]=> float(20.46) [“temp_min”]=> float(20.46) [“temp_max”]=> float(21.04) [“pressure”]=> float(1014.57) [“sea_level”]=> float(1014.57) [“grnd_level”]=> float(1011.64) [“humidity”]=> int(70)…….省略

    あとはこれをこっちで整形して、視覚的に人間がちゃんと見れるようにしていきます。

    5日間天気予報

    5日間天気予報(Call 5 day / 3 hour forecast data)の値一覧

    まとめるとこんな感じです。

    123概要
    code内部パラメーター
    message内部パラメーター
    cityid都市ID
    name市の名前
    coordlat緯度
    lon経度
    country国コード(GB、JPなど)
    timezoneUTCから秒単位でシフト
    cntこのAPI呼び出しによって返された行数
    listdt予測されるデータの時間、Unix、UTC
    maintemp温度。単位のデフォルト:ケルビン、メトリック:摂氏、帝国:華氏。
    temp_min計算時の最低温度。
    temp_max計算時の最高温度。
    pressureデフォルトでの海面の気圧、hPa
    sea_level海面の気圧、hPa
    grnd_level地上レベルの気圧、hPa
    humidity湿度、%
    temp_kf内部パラメーター
    weatherid気象条件ID
    main気象パラメータのグループ(雨、雪、極端など)
    descriptionグループ内の気象条件
    icon天気アイコンID
    cloudsall曇り、%
    windspeed風速。単位のデフォルト:メートル/秒、メトリック:メートル/秒、帝国:マイル/時間。
    deg風向、度(気象)
    rain3h過去3時間の降雨量、mm
    snow3h過去3時間の積雪量
    dt_txt計算のデータ/時間、UTC

    5日間天気予報の値を出力

    主に天気予報で使えるのは情報はlist配下なので、list配下だけ使っていきます。

    foreachでループさせ、foreach内で変数に格納した値をHTMLに組み込んでください。

    タイムスタンプ 協定世界時 (UTC)を日本標準時 (JST)に変換

    APIが返してくる日時(タイムスタンプ)はUTCで、日本時間ではないので、これを日本時間に変換します。

    • new DateTimeでインスタンスを生成
    • setTimestampでAPIが返したタイムスタンプをセット
    • setTimeZonenew DateTimeZone('Asia/Tokyo')で東京を指定

    天気説明(description)を日本語に翻訳

    海外のAPIなので、返ってくる値も英語です。
    自力で翻訳することにします。
    – 近いうちに別の翻訳APIを使って翻訳しようと思います。。

    ユーザー定義関数getTranslation()を作りました。
    下記公式ドキュメントから、どんなdescriptionがあるか記載されているので、ここを参照して力技で翻訳します。
    https://openweathermap.org/weather-conditions

    アイコンを出力

    公式アイコンをそのまま利用

    下記公式ドキュメントに出力されるアイコンも記載されています。
    https://openweathermap.org/weather-conditions

    $weather_icon = $items['weather'][0]['icon']; // 天気アイコン(公式のアイコンを使用)
    をそのまま利用し、アイコンを簡単に出力できます。

    自分で用意したアイコンを利用

    これも力技でdescriptionから加工して、画像ファイル名にして出力したいと思います。
    descriptionから加工する理由は、公式だと小雨も大雨も同じアイコンなので、そこの違いの幅を持たせたいからです。

    ユーザー定義関数getIcon()を作りました。

    フリーのSVG素材を利用して、天気アイコンを出力します。

    ここまでで、5日間3時間天気予報は出来上がりましたね。

    ユーザーが見たい都市に切り替えられるようにする

    セレクトボックスでユーザーが都市を切り替えられるようにします。
    まずは、都市一覧の連想配列を作りました。

    キーが都市IDで、値が都市名です。
    これをベースに組んでいきます。

    selectボックスを作成

    配列エリアリスト$areasからループで作成します。

    都市IDを動的に取得

    ユーザーがフォームで送信した先ほどのselectボックスの値を使ってIDをセットします。
    三項演算子で$_GET['area']があったら$_GET['area']の値、
    なかったら配列エリアリスト$areasの最初のキー、つまり東京都のIDをセットします。

    try-catchで不正なIDをブロック

    get送信で値を受け渡すので、普通にURLでパラメーターでIDをいじられたらAPI取得プログラムにエラーが発生するので、それを防ぎます。

    $_GET['area']の値が$areasに含まれているか検証します。
    不正の場合エラーを渡し、エラー文を出力させます。

    値を取得

    あとは先ほどまで入れていた東京都のID1850144を動的に変数にして、ユーザー定義関数getWeather()に渡すだけです。

    現在の天気データ

    現在の天気データ(Current weather data)値一覧

    12概要
    coordlon経度
    lat緯度
    weatherid気象条件ID
    main気象パラメータのグループ(雨、雪、極端など)
    descriptionグループ内の気象条件
    icon天気アイコンID
    base内部パラメーター
    maintemp温度。単位のデフォルト:ケルビン、メトリック:摂氏、帝国:華氏。
    pressure大気圧(海面上、sea_levelまたはgrnd_levelデータがない場合)、hPa
    humidity湿度、%
    temp_min現時点での最低気温。
    temp_max現時点での最高温度。
    sea_level海面の気圧、hPa
    grnd_level地上レベルの気圧、hPa
    windspeed風速。単位のデフォルト:メートル/秒、メトリック:メートル/秒、帝国:マイル/時間。
    deg風向、度(気象)
    cloudsall曇り、%
    rain1h過去1時間の降雨量、mm
    3h過去3時間の降雨量、mm
    snow1h過去1時間の積雪量、mm
    3h過去3時間の積雪量、mm
    dtデータ計算の時間、Unix、UTC
    systype内部パラメーター
    id内部パラメーター
    message内部パラメーター
    country国コード(GB、JPなど)
    sunrise日の出時間、Unix、UTC
    sunset日没時間、Unix、UTC
    timezoneUTCから秒単位でシフト
    id都市ID
    mane市の名前
    cod内部パラメーター

    現在の天気情報を取得、出力

    ▼ 公式ドキュメント
    https://openweathermap.org/current

    リクエスト方法は5日間天気と同様です。

    • 現在の天気 ⇒ weather
    • 5日間の3時間予報 ⇒ forecast

    現在の天気情報を取得

    ユーザー定義関数getWeather()の第一引数でweatherを指定します。

    現在の天気情報を出力

    使用ユーザー定義関数などは5日間天気と同様です。

    『Lazy Line Painter』でアイコンをSVGアニメーションさせる

    SVGアニメーションは『Lazy Line Painter』を利用して楽します。
    SVGフリー素材を入手して、それを『Lazy Line Painter』を使って動かします。

    SVGがソースコードにあると邪魔で可読性が落ちるので、アイコン1つ毎に別ファイル化させました。
    そのインクルード先を動的に変更することによってアイコンを出し分けます。
    wordpressなので、get_template_partを使います。

    最終 完成版ソース

    – PHP、HTML

    – JavaScript

    selectボックスで都市を選択したらフォーム送信と、SVGアニメーション用に使ってます。

    『Lazy Line Painter』はコールバック関数もあり、アニメーション終了後に処理させることができます。
    今回はアニメーション後にクラスを追加して、SVGのfillstrokeの色付けなどを行っています。

    完成サイト

    5日間の3時間天気予報

    公式APIドキュメント まとめ