LuftGarden - 熊本のWebサイト・ホームページ制作スタジオ

BLOG技術ブログ

Laravel + Vue.js で出席管理Webアプリを作成する – Part.2

はじめに

Laravel + Vue.js で出席管理Webアプリを作成する – Part.1」の続きになります。

Part.1 ではLaravel開発環境のセットアップからダミーデータの作成まで行いました。
今回からは、いよいよ出席管理のAPI作成を行っていきます。

APIのルーティング設定

APIの仕様は以下のとおりです。

api/attendances (GET) 全ての出席登録を取得して返す
api/attendances/:id (GET) 指定されたIDの出席登録のみを取得して返す
api/attendances (POST) 新しい出席を登録する
api/attendances/:id/report (PUT) 通報用のエンドポイント

routes/api.phpを編集し、APIのルーティングを設定します。

routes/api.php
<?php

use Illuminate\Http\Request;

Route::resource('attendances', 'Api\AttendancesController')
    ->only(['index', 'show', 'store']);

Route::put('attendances/{attendance}/report', 'Api\ReportAttendancesController@update');

Route::resourceで  Resourceful なルーティングをワンライナーで記述することが可能です。

 Laravelのルーティング書き方まとめ – Qiita
 《REST思想》と《リソース指向》と《Webページ》を一緒にしてはいけない – Qiita

Controllerの設定

ルーティングが決まったら、API向けのコントローラを用意していきます。

AttendancesController の作成

$ php artisan make:controller Api/AttendancesController

app/Http/Controllers/Api/AttendancesController.phpが作成されるので、以下のように編集します。

app/Http/Controllers/Api/AttendancesController.php
<?php

namespace App\Http\Controllers\Api;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Attendance;  // *1
use App\Http\Resources\AttendanceResource;  // *2

class AttendancesController extends Controller
{
    public function index()
    {
        $attendances = Attendance::latest()
            ->ignoreFlagged()  // *3
            ->paginate(20);

        return AttendanceResource::collection($attendances);
    }

    public function show(Attendance $attendance)
    {
        return new AttendanceResource($attendance);
    }

    public function store(Request $request)
    {
        $attendance = $this->validate( $request, [
            'name'  => 'required|min:3|max:50',
            'email' => 'required|email',
            'body'  => 'required|min:3',
        ] );

        $attendance = Attendance::create($attendance);

        return new AttendanceResource($attendance);
    }
}

ignoreFlaggedスコープやAttendanceResourceクラスは未定義のため、現段階でブラウザ表示するとエラーになりますが気にしなくてOKです。それぞれの意味は以下のようになります。

*1 例えば、CakePHPではController::loadModel()でModelを呼び出しますが、Laravelでは単純に namespace の参照で使用します。
*2 Resourceクラス(後述)です。詳細は 公式ドキュメントから。
*3 クエリースコープです。 こちらの記事が参考になります。

クエリースコープの設定

さきほどのignoreFlaggedスコープを設定するため、Model側を編集します。

app/Attendance.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Attendance extends Model
{
    protected $fillable = [
        'name',
        'email',
        'body',
        'flagged_at',
        'updated_at',
    ];

    // 以下を追加

    /**
     * [QueryScope] 通報済みユーザの除外
     * 
     * @param $query
     * @return mixed
     */
    public function scopeIgnoreFlagged($query)
    {
        return $query->where('flagged_at', null);
    }
}

ignoreFlagged()というクエリースコープを用意することで、SQLのwhere句として`flagged_at` IS NULLという条件の役割を持たせることが可能になります。

先述した  クエリースコープの参考記事 にも記載されていますが、条件ごとにスコープを切ることができるため、可読性が良くなるメリットがあります。

ReportAttendancesController の作成

$ php artisan make:controller Api/ReportAttendancesController

app/Http/Controllers/Api/ReportAttendancesController.phpが作成されるので、以下のように編集します。

app/Http/Controllers/Api/ReportAttendancesController.php
<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\AttendanceResource;
use App\Attendance;

class ReportAttendancesController extends Controller
{
    /**
     * 通報処理
     *
     * @param Attendance $attendance
     * @return AttendanceResource
     */
    public function update( Attendance $attendance )
    {
        $attendance->flag();

        return new AttendanceResource($attendance);
    }
}

通報処理を行うflag()メソッドをModel側に作成します。

app/Attendance.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;  // 追加

class Attendance extends Model
{
    // 中略

    /**
     * 通報処理(flagged_at の更新)
     * 
     * @return bool
     */
    public function flag()
    {
        return $this->update( [ 'flagged_at' => Carbon::now() ] ); // *1
    }
}
*1  CarbonはPHPのDateTimeクラスをオーバーラップした日付操作ライブラリです。Laravelには標準で組み込まれています。

Resourceの設定

Resourceクラスは、返却するデータの構造やフォーマットを調整する役割を担います。

AttendanceResource の作成

$ php artisan make:resource AttendanceResource

app/Http/Resources/AttendanceResource.phpが作成されるので、以下のように編集します。

app/Http/Controllers/Api/AttendancesController.php
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\Resource;

class AttendanceResource extends Resource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id'     => $this->id,
            'name'   => $this->name,
            'avatar' => $this->avatar,  // *1
            'body'   => $this->body,
            'date'   => $this->created_at->diffForHumans()  // *2
        ];
    }
}
*1 スキーマには存在しないデータですが、アバター画像を取得するメソッドを用意します(後述)。
*2  CarbondiffForHumans()メソッドを使用しています。Laravelではデフォルトでcreated_atupdated_atフィールドに対して使用可能です。詳細は 公式ドキュメントを参照してください。

次に、 Gravatarからアバター画像を取得するメソッドをModel側に追加しておきます。

app/Attendance.php

public function getAvatarAttribute()
{
    return sprintf( 'https://www.gravatar.com/avatar/%s?s=100', md5( strtolower( trim( $this->email ) ) ) );
}

GravatarのAPIでは、メールアドレスをmd5ハッシュしたパラメータを渡すとアバター画像のURLを取得することができます。
 PHP Image Requests – Gravatar

上記のように、get[プロパティ名]Attribute()という命名規則でメソッド定義しておくことで、スキーマには存在しないような独自の値を返却することも可能になります。

動作確認

APIの動作確認には Postmanが便利です。

一覧表示 – api/attendances (GET)

http://homestead.test/api/attendancesにGETでリクエストします。
正常にレスポンスが返ってきたらOKです(以下はPostmanの画面キャプチャ)。

一覧表示のリクエストを送信した際のPostmanの画面キャプチャ

個別表示 – api/attendances/:id (GET)

http://homestead.test/api/attendances/[出欠ID]にGETでリクエストします。

個別表示のリクエストを送信した際のPostmanの画面キャプチャ

出席登録 – api/attendances (POST)

http://homestead.test/api/attendancesにPOSTでリクエストします。
パラメータは以下のように設定しました。

name テスト太郎
email test@example.com
body Hello, Laravel attendances API!

出席登録のリクエストを送信した際のPostmanの画面キャプチャ

ユーザの通報 – api/attendances/:id/report (PUT)

http://homestead.test/api/attendances/[出欠ID]/reportにPUTでリクエストします。

ユーザの通報リクエストを送信した際のPostmanの画面キャプチャ

おわりに

以上で Part.2 の工程は終了です。
Part.3 からは、Vue.jsを使用したビューを作成していきます。

PAGETOP