LoginSignup
6
9

More than 3 years have passed since last update.

Laravelアプリ同士をWeb APIで連携させるには

Last updated at Posted at 2020-06-27

オンプレで動く Laravel と、クラウドで動く Laravel を、Web API でシステム間連携させてみた話。
image.png

やりたいこと

社内オンプレの給与明細APサーバにアクセスすると、クラウドの勤怠打刻APサーバのデータも取得し、給与明細と合わせて勤怠実績明細も表示できるようにする。
シーケンス図で書くと次のようになる。
image.png
勤怠実績明細の表示例。
image.png

Web API の設計

設計時に決めておくべき項目。

  • HTTPメソッド
    GET

  • エンドポイント
    /api/v1/kintai/{yyyyMM}/{勤怠個人番号}

  • 機能概要
    従業員の勤怠実績データを返す

  • リクエスト

    • yyyyMM ・・・ 年月("last" と指定された場合は最終年月とする)
    • 勤怠個人番号 ・・・ 従業員の勤怠個人番号(Active Directory に照会すること)
  • レスポンス

    • ステータスコード
      • 200 ・・・ 成功
      • 404 ・・・ リクエストされた勤怠実績が存在しなかった
    • 応答形式 ・・・ JSON

REST APIはステートレスなので、認証にCookieやセッションは使えない。APIではトークン認証BASIC認証が一般的だが、今回は社内限定利用ということもあり、簡素化のため認証は省略する。

(参考) クラウド人事労務パッケージのAPI

Laravelでの実装方法

勤怠打刻APサーバ

APIが呼ばれる側のサーバ。
api.phpにエンドポイントを定義する。web.phpとは違いapi.phpにはCSRF保護が無い。

routes\api.php
Route::get('v1/kintai/{yyyymm}/{id}', 'Api\KintaiController@index');

呼ばれるコントローラを作成する。

app\Http\Controllers\Api\KintaiController.php
<?php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Models\Result;
use Carbon\Carbon;
use App\Http\Controllers\Controller;

/*
  給与明細サーバから呼ばれるクラス
*/
class KintaiController extends Controller
{
    public function index(Request $request, $yyyymm, $syaincd)
    {
        if ($yyyymm == 'last') {  // last指定時は最終年月を仮定
            $yyyymm = Carbon::yesterday()->format('Ym');
        }
        $baseDate = Carbon::create(substr($yyyymm, 0, 4), substr($yyyymm, 4, 2), 1);  // 基準日の設定

        // 勤怠実績データベースの読み込み
        $query = Result::where('syaincd', $syaincd)
            ->whereBetween('kintaijissekiymd', array($baseDate->copy()->startOfMonth()->format('Ymd'), $baseDate->copy()->endOfMonth()->format('Ymd')))
            ->orderBy('kintaijissekiymd');

        // レコード件数が0より大きければデータを返し、そうでなければエラーレスポンスとする
        if ($query->count() > 0) {
            return response()->json([
                'code'     => 200,
                'contents' => $query->get()
              ], 200);
        } else {
            return response()->json([
                'code'     => 404,
                'message'  => 'Not Found'
              ], 404);
        }
    }
}

Eloquentモデルでは、文字列にキャストされるときJSONに変換されるため、Eloquentオブジェクトをそのまま返しても良い。

コマンドからAPIをテストする

curlコマンドで得られるJSONデータをjqコマンドで整形して確認。

シェルからコマンドを実行
curl -s https://example.com/api/v1/kintai/202006/12765 | jq
Pythonの場合
import requests
res = requests.get('https://example.com/api/v1/kintai/202006/12765')
print(res.json())
出力結果
{
  "code": 200,
  "contents": [
    {
      "syaincd": 12765,
      "syainmei": "山田 太郎",
      "kanrisyouninkengencode": "一般社員",
      "kintaijissekiymd": "20200625",
      "syugyozikantaikaishihhmi": "0850",
      "syugyozikantaisyuryohhmi": "1730",
      "meisyo": "出勤",
      "barcodesyukkinhhmi": "0842",
      "barcodetaikinhhmi": "1738",
      :

給与明細APサーバ

APIを呼ぶ側のサーバ。
昨今のWebアプリでは、APIで取得したデータはフロントエンドの Vue や React で表示することが多いが、ここではLaravelで受けてビュー(Blade)に渡す。

app\Http\Controllers\KintaiController.php(一部抜粋)
$context = stream_context_create(array(
  'http' => array('ignore_errors' => true)
));
$kintaicd = $request->session()->get('user')->kintaicd;
// APIを呼び出す
$json = file_get_contents("https://example.com/api/v1/kintai/$yyyymm/$kintaicd", false, $context);
$ary = json_decode($json);  // JSONを配列に

// 正常なら "contents" をViewに渡す
if ($ary->code == 200) {
    $reports = $ary->contents;
} else {
    $reports = null;
}

return view('kintai', compact('reports'))
   ->with('spec_type', 'kintai')
   ->with('ym', substr($yyyymm, 0, 4) . '年' . ltrim(substr($yyyymm, 4, 2), '0') . '月')
   ->with('prev_month', $dt->copy()->subMonth(1)->format('Ym'))
   ->with('next_month', $dt->copy()->addMonth(1)->format('Ym'));

ビュー(Blade)で $reports を展開する。

resources\views\kintai.blade.php
<div class="table-responsive">
    <table class="table text-nowrap table-bordered table-striped table-hover table-condensed">
      <thead>
      <tr>
        <td rowspan="2">日付</td>
        <td rowspan="2">勤怠種別</td>
        <td colspan="2">打刻</td>
         省略
      </tr>
      <tr>
        <td>出勤</td>
        <td>退勤</td>
        <td>就業開始</td>
         省略
      </tr>
      </thead>
      <tbody>
      @foreach ($reports as $report)
      <tr>
          <td>{{ $report->kintaijissekiymd }}</td>
          <td>{{ $report->syukkinhhmi }}</td>
          <td>{{ $report->taikinhhmi }}</td>
           省略
      </tr>
      @endforeach
      </tbody>
    </table>
</div>
6
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
9