Engineering

Oct 14, 2017

Laravel5.4とVue.jsでSPAを作ってみる。③ -仮想通貨の価格を取得するページを作ってみる-

前回、前々回と 環境の構築、 クライアント側でのルーティング設定を 行いました。

Laravel5.4とVue.jsでSPAを作ってみる。① -環境構築-

Laravel5.4とVue.jsでSPAを作ってみる。② -クライアントルーティング-

今回は、 実際にAjax通信を使ったより実践的で、 現実に即した内容をお届けできればと思います。

さて、 作成する内容ですが、 仮想通貨の価格をコインチェックのAPIを利用して取得 →リアルタイムで画面で価格を表示とします。

出来上がったものはこちらです。

コインチェックのAPIを利用して、 実に14種類の仮想通貨のレートを確認できるようにしています。

内部でやっていることは

  1. 同サーバDB内の仮想通貨の一覧を取得
  2. 1.のそれぞれの仮想通貨に関して価格を取得

です。

同サーバDB内の仮想通貨の一覧を取得

マイグレーションを書いてDB に仮想通貨の情報を登録します。


use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use App\Models\Currency;

class CreateCurrencies extends Migration
{
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up()
  {
    Schema::create('currencies', function (Blueprint $table) {
      $table->increments('id');
      $table->string('key');
      $table->string('name_ja');
      $table->string('name_en');
      $table->timestamps();
    });

    $data = [
      ['key' => 'btc','name_ja' => 'ビットコイン' , 'name_en' => 'BitCoin'],
      ['key' => 'bch','name_ja' => 'ビットコインキャッシュ' , 'name_en' => 'BitCoinCash'],
      ['key' => 'eth','name_ja' => 'イーサリアム' , 'name_en' => 'Etherium'],
      ['key' => 'etc','name_ja' => 'イーサリアムクラシック' , 'name_en' => 'Etherium Classic'],
      ['key' => 'dao','name_ja' => 'DAO' , 'name_en' => 'DAO'],
      ['key' => 'lsk','name_ja' => 'リスクコイン' , 'name_en' => 'BitCoin'],
      ['key' => 'fct','name_ja' => 'ファクトム' , 'name_en' => 'Factom'],
      ['key' => 'xmr','name_ja' => 'モネロ' , 'name_en' => 'Monero'],
      ['key' => 'rep','name_ja' => 'オーガー' , 'name_en' => 'Augur'],
      ['key' => 'xrp','name_ja' => 'リップル' , 'name_en' => 'Ripple'],
      ['key' => 'zec','name_ja' => 'ジーキャッシュ' , 'name_en' => 'Zcach'],
      ['key' => 'xem','name_ja' => 'ネム' , 'name_en' => 'Xem'],
      ['key' => 'ltc','name_ja' => 'ライトコイン' , 'name_en' => 'Litecoin'],
      ['key' => 'dash','name_ja' => 'DASH' , 'name_en' => 'DASH'],
    ];
    Currency::insert($data);
  }

  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down()
  {
    Schema::drop('currencies');
  }
}

マイグレーション実行

php aritsan migrate

これでDatabaseの準備はできたので、 これをAjaxでとってきて表示させるまでやりましょう。

APIのルーティング設定。

routes/api.php

<?php use Illuminate\Http\Request;
 use App\Models\Currency;
use GuzzleHttp\Client;
Route::group(['middleware' => 'api'], function() {
  Route::get('currencies',  function() {
    $obj = new Currency();
    $result = $obj->all();
    return json_encode($result);
  });
});

これで /api/currenciesにアクセスすると、 json形式の仮想通貨の情報を取得できるようになります。 (ルーティングファイルに処理を書くという。。まあチュートリアルでもやってたし。。) お次は表示するVueコンポーネントです。

<template>
  <div class="container">
    <div class="row">
      <div class="col-md-8 col-md-offset-2">
        <div class="panel panel-default">
          <div class="panel-heading">Crypto Currencies</div>

          <div class="panel-body">
            <p>{{message}}</p>
            <ul class="list-unstyled" v-if="is_init">
              <li v-for="(currency, key) in currencies" >
                <span v-on:click="loading">
                  <router-link :to="{ path: '/currencies/' + currency.key }" >{{currency.name_ja}} / {{currency.name_en}}</router-link>
                </span>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  created() {
    this.fetchCurrencies(),
  },
  data() {
    return {
      is_init: false,
      message: "Fetching Data..."
    }
  },
  methods: {
    loading(){
      this.is_loading = true;
      this.message = "Fetching Data...";
    },
    fetchCurrencies() {
      axios.get('/api/currencies')
      .then(res =>  {
        this.currencies = res.data;
        this.is_loading = false;
        this.is_init = true;
        this.message = "";
      });
    }
}
</script>

ここまででとりあえず、仮想通貨の一覧を取得はできて、 Ajax通信も使えています。

demo

が、ここまでだとリアルタイムに価格を表示していく!! というSPAの面白さみたいなものがないので、 さらにそれぞれの価格を取得するように修正していきます。

APIで仮想通貨の価格を取得する

APIはこちらのコインチェックのAPIを使用します。 https://coincheck.com/ja/documents/exchange/api

価格設定の部分のAPIのルーティングを設定します。 routes/api.phpに以下のルーティングを設定します。

Route::get('rate/{currency}',  function($currency) {
        $res = [ 'currency' => $currency ,'btc' => 0 , 'jpy' => 0 ];
        if ( $res['currency'] === ''){
            $res['currency'] = 'btc';
        }
        $client = new Client();
        $url = "https://coincheck.com/api/rate/${currency}_jpy";
        $response = $client->request('GET',$url);
        $res['jpy'] = json_decode($response->getBody())->rate;

        if($currency != 'btc'){
            $url = "https://coincheck.com/api/rate/${currency}_btc";
            $response = $client->request('GET',$url);
            $res['btc'] = json_decode($response->getBody())->rate;
        }

        if ($response->getStatusCode() === 200) {
            return response()->json($res);
        } else {
            return json_encode(['error']);
        }
    });

ここでは、 仮想通貨の円建て、ビットコイン建てのレートを取得して 返却しています。

次に、Index.vueのhtml部分に以下のタグを追加し、

<div class="row">
    <div class="col-md-8 col-md-offset-2">
    <div class="panel panel-default">
      <div class="panel-heading">Crypto Currency Rate</div>

      <div class="panel-body">
      <p>{{message}}</p>
      <ul class="list-unstyled" v-if="!is_loading">
        <li>
        1{{name.toUpperCase()}} =   <span class="h2">{{currency.jpy.toLocaleString()}}</span> JPY
        </li>
        <li v-if="name != 'btc'">
        1{{name.toUpperCase()}} =   <span class="h2">{{currency.btc.toLocaleString()}}</span> BTC
        </li>
      </ul>

      </div>
    </div>
    </div>
  </div>

javascipt部分を以下のようにします。

<script>
export default {
  created() {
    this.fetchCurrencies(),
    this.fetchRate(),
    this.timer = setInterval(this.fetchRate, 2000)
  },
  props:['name'],
  data() {
    return {
      currency: { 'currency':'', 'jpy': 0 , 'btc':0 },
      is_init: false,
      is_loading: true,
      message: "Fetching Data..."
    }
  },
  methods: {
    loading(){
      this.is_loading = true;
      this.message = "Fetching Data...";
    },
    fetchCurrencies() {
      axios.get('/api/currencies')
      .then(res =>  {
        this.currencies = res.data;
        this.is_loading = false;
        this.is_init = true;
        this.message = "";
      });
    },
    fetchRate() {
      if (this.name === undefined){
        this.name = 'btc';
      }
      axios.get('/api/rate/' + this.name)
      .then(res =>  {
        this.currency.btc = res.data.btc;
        this.currency.jpy = res.data.jpy;
        this.name = res.data.currency;
        this.is_loading = false;
        this.message = "";
      });

    },
    cancelAutoUpdate: function() {
      clearInterval(this.timer)
    }
  },
  beforeDestroy() {clearInterval(this.timer)}
}
</script>

あとは、cssなどを多少直すと 上の動画のような感じになります。

コードはここに置いておきます。

https://github.com/version-1/spa-sample

まとめ

以上、ここまでで クライアント側でレンダリングして、 必要なデータはAPIでとってくる。 という感じでサクサク動くSPAを作ってきました。

基本の部分は紹介したので、 あとは各々の興味次第という感じですね。

構築した感想としては、 ユーザ側からの使用感として、リロードの待ち時間が短くすみ サクサク動くという点で良い気がきましたが、 やはりコードの管理が煩雑になりそうな気がしています、 ビュー側でそれなりのコードを各必要があるのでコード量が多くなり 大変そうです。

あとは、以前にも仮想通貨の価格を取得する記事を 書いたのですが、そこからビットコインの価格が5,6倍とかに なっています。 恐ろしや。。

[Node.js]ビットコインの価格をリアルタイムにDBに保存する。

以上です!!

 

関連記事

記事検索

気になるサイト内の記事を検索する

プロフィール

バンクーバー在住のフルスタックエンジニアです。React, Ruby on Rails, Go などでお仕事しています。職場がトロントなので日本、トロント、バンクーバーの三つの時天空を操って生活しています。

プロモーション