Nuxt+Vuetify+Laravelで予定確認カレンダーを作りました!【RESTAPI作成】

サムネイル
目次
  1. 開発環境
  2. ロードマップ
  3. マイグレーションファイルを使ってテーブル作成
    • マイグレーションファイルの作成
    • マイグレーションファイルの編集
    • マイグレーションファイルの実行
  4. データ操作のためのモデルを作成
    • モデルの作成
    • モデルの編集
  5. コントローラを作成してAPIの処理を実装
    • コントローラの作成
    • コントローラの編集
      • indexメソッド
      • storeメソッド
      • showメソッド
      • updateメソッド
      • destroy メソッド
  6. ルーティングの設定
  7. RESTAPIの動作確認

開発環境

OSWindows10
エディタVisual Stuido Code
開発環境XAMPP
データベースMySQL
フロントエンドNuxt, Vuetify
バックエンドLaravel

ロードマップ

マイグレーションファイルを使ってテーブル作成

マイグレーションファイルとは、データベースの設計図のようなものです。

カラムデータ型などのテーブルの定義を書いておくことで、コマンドを実行するだけで自動でテーブルを作成してくれます。

マイグレーションファイルの作成

aritsanのmakeコマンドでcalendarという名前のマイグレーションファイルを作成します。

名前は任意のもので構いません。

php artisan make:migration calendar

マイグレーションファイルの編集

マイグレーションファイルが作成出来たらプログラムを編集していきます。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class Calendar extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('calendars', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->date('start_date')->format('YYYY-MM-DD');
            $table->date('end_date')->format('YYYY-MM-DD');
            $table->string('color');
            $table->text('content')->nullable();
            $table->timestamps();
        });
    }

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

up関数にテーブルの定義に関する処理を記述していきます。

まずはSchema::create関数の第1引数にはテーブル名、第2引数は構造定義のコールバック関数を指定します。

今回はcalendarsという名前のテーブルを作成します。

 Schema::create('calendars', function (Blueprint $table) {
    // callback
 });

次にコールバック関数の中に構造定義を記述していきます。

詳しい説明は割愛するので、詳細は公式ドキュメントを参照してください。

Schema::create('calendars', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->date('start_date')->format('YYYY-MM-DD');
    $table->date('end_date')->format('YYYY-MM-DD');
    $table->string('color');
    $table->text('content')->nullable();
    $table->timestamps();
});

マイグレーションファイルの実行

artisanのmigrateコマンドで先程作成したマイグレーションファイルを実行します。

php artisan migrate

このコマンドを実行すると全てのマイグレーションファイルを実行します。

特定のマイグレーションファイルのみを実行する場合はオプションを付けて実行します。

php artisan migrate:refresh --step=1  --path=/database/migrations/[マイグレーションファイル名].php 

Migration table created successfully.」と表示されれば作成完了です。

もしやり直したい場合は、php artisan migrate:rollbackでマイグレーションしたテーブルを消しましょう。

エラーが出る場合はデータベースの接続ができていないか、データベースの側が起動されていないので確認しましょう。

データ操作のためのモデルを作成

モデルとはデータベースのデータ操作の機能を持ったクラスのことです。

データベースの操作はSQLを使うのが一般的ですが、モデルを使うことでPHPのメソッドでSQLと同等のことができます。

データを取得したり削除したりする時はモデルを経由して行います。

モデルの作成

artisanのmakeコマンドでCalendarというモデルを作成します。

php artisan make:model Calendar

オプションでCarendarの後ろに「--migration」を付けることにより、モデルとマイグレーションファイルを同時に作成することも可能です。

モデルの編集

モデルを作成したら$fillableを設定します。

$fillableは複数代入のホワイトリストのことです。複数代入とは複数のカラムにデータを入れることです。Laravelの仕様で複数代入はデフォルトで禁止されています。なので処理したいカラム名をあらかじめ$fillableに設定しておきます。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Carendar extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'start_date',
        'end_date',
        'color',
        'content',
    ];
}

コントローラを作成してAPIの処理を実装

コントローラは主に2つの役割を持っています。

  • ルートから受け取った情報をモデルに処理をお願いする
  • モデルから受け取った情報をビューに表示する

具体的にはモデルからDBにアクセスし、取得したデータをコントローラで加工してビューに渡したり、ビューからのデータをコントローラで受け取りモデルに渡し、DBに保存をしたりと、モデルとビューの橋渡しをする存在です。

今回ビューはLaravelではなくNuxtで作るので、コントローラとNuxtの橋渡しのためにRESTAPIを作ります。

コントローラの作成

artisanのmakeコマンドでCalendarControllerというコントローラーを作成します。

php artisan make:controller CalendarController --api

--apiというオプションをつけることでindex, store, show, update, destoroyなど、API作成で使うであろうメソッドが初めから書かれた雛形が作られます。--resourceにするとそれ以外のcreate, editが追加された雛形のファイルを作成できます。

雛形で作られたメソッドはあくまでも雛形で、特にメソッド名に決まりは無いので、自分の分かりやすい名前にしてもらって構いません。ただし雛形通りに作ると後述するルーティングの設定が楽になるので、特別なことが無い場合は雛形をそのまま使う方が良いです。

今回は雛形通りに処理を実装していきます。

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
 
class CalendarController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }
 
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }
 
    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }
 
    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }
 
    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

コントローラの編集

データベースとやり取りしたいので先程作成したモデルをインポートするためにuse App\Models\Calendar;を追加します。

また受け取った値に対してバリデーションをしたいので、useIlluminate\Support\Facades\Validator;も追加しておきます。

use Illuminate\Support\Facades\Validator; 
use App\Models\Calendar;

コントローラ全体はこのような感じになっています。各メソッドでの処理について説明します。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

//追加
use Illuminate\Support\Facades\Validator; 
use App\Models\Calendar;


class CalendarController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $calendars = Calendar::all();
        return response()->json([
            'data' => $calendars
        ], 200, [], JSON_UNESCAPED_UNICODE);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request,$id)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required',
            'start_date' => 'required',
            'end_date' => 'required',
            'color' => 'required',
            'content' => 'required'
        ]);

        $calendar = Calendar::create($request->all());
        

        if ($calendar) {
            if ($validator->fails()) {
                return response()->json([
                    'message' => 'Bad Request',
                ], 400);
              } else {
                $id = Calendar::table('calendars')->max('id') + 1;
                return response()->json([
                    'id' => $id,
                ], 201);
              }
        } else {
            return response()->json([
                'message' => 'Not found',
            ], 404);
        }
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
        $calendar = Calendar::find($id);
        if ($calendar) {
            return response()->json([
                'data' => $calendar
            ], 200, [], JSON_UNESCAPED_UNICODE);
        } else {
            return response()->json([
                'message' => 'Not found',
            ], 404);
        }
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Calendar $calendar) //$id から Calendar $calendar に変更
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required',
            'start_date' => 'required',
            'end_date' => 'required',
            'color' => 'required',
            'content' => 'required'
        ]);

        if ($calendar) {
            if ($validator->fails()) {
                return response()->json([
                    'message' => 'Bad Request',
                ], 400);
              } else {
                $calendar->fill($request->all())->save();
                return 204;
              }
        } else {
            return response()->json([
                'message' => 'Not found',
            ], 404);
        }
        
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Calendar $calendar) //$id から Calendar $calendar に変更
    {
        if ($calendar) {
            $calendar->delete();
            return 204;
            //HTTPステータスコードの204 No Content
            //訳すると内容なし。HTTPステータスコードとして204を返すのなら、
            //その名の通りレスポンスボディーは何も返さないのが正解
        } else {
            return response()->json([
                'message' => 'Not found',
            ], 404);
        }
    }
}

indexメソッド

indexメソッドでは全てのカレンダー情報を取得するメソッドです。

public function index()
{
    $calendars = Calendar::all();
    return response()->json([
        'data' => $calendars
    ], 200, [], JSON_UNESCAPED_UNICODE);
}

storeメソッド

storeメソッドは入力したカレンダー情報を登録するメソッドです。

受け取った値は$requestに格納されており、最初にValidator::makeで全ての項目が入力されているかをチェックしています。

もし1つでも未入力の項目があると400 Bad Requestを返します。

カレンダーの登録が成功すると登録したカレンダーのidを返します。

public function store(Request $request,$id)
{
  $validator = Validator::make($request->all(), [
    'name' => 'required',
    'start_date' => 'required',
    'end_date' => 'required',
    'color' => 'required',
    'content' => 'required'
  ]);

  $calendar = Calendar::create($request->all());

  if ($calendar) {
    if ($validator->fails()) {
      return response()->json([
        'message' => 'Bad Request',
      ], 400);
    } else {
      $id = Calendar::table('calendars')->max('id') + 1;
      return response()->json([
        'id' => $id,
      ], 201);
    }
  } else {
    return response()->json([
      'message' => 'Not found',
    ], 404);
  }
}

showメソッド

showメソッドはidからカレンダー情報を取得するメソッドです。

データが存在すればそのデータを返し、存在しなければ「404 Not Found」を返します。

public function show($id)
{
  //
  $calendar = Calendar::find($id);
  if ($calendar) {
    return response()->json([
      'data' => $calendar
    ], 200, [], JSON_UNESCAPED_UNICODE);
  } else {
    return response()->json([
      'message' => 'Not found',
    ], 404);
  }
}

updateメソッド

updateメソッドはカレンダー情報を更新するメソッドです。

処理はほとんどstoreメソッドと同じで、storeメソッドでは新規でデータ登録し、updateメソッドでは登録してあるデータを更新します。

public function update(Request $request, Calendar $calendar) //$id から Calendar $calendar に変更
{
  $validator = Validator::make($request->all(), [
    'name' => 'required',
    'start_date' => 'required',
    'end_date' => 'required',
    'color' => 'required',
    'content' => 'required'
  ]);
  if ($calendar) {
    if ($validator->fails()) {
      return response()->json([
        'message' => 'Bad Request',
      ], 400);
    } else {
      $calendar->fill($request->all())->save();
      return 204;
    }
  } else {
    return response()->json([
      'message' => 'Not found',
    ], 404);
  }  
}

destroy メソッド

destroyメソッドはカレンダー情報を削除するメソッドです。

public function destroy(Calendar $calendar) //$id から Calendar $calendar に変更
{
        if ($calendar) {
            $calendar->delete();
            return 204;
            //HTTPステータスコードの204 No Content
            //訳すると内容なし。HTTPステータスコードとして204を返すのなら、
            //その名の通りレスポンスボディーは何も返さないのが正解
        } else {
            return response()->json([
                'message' => 'Not found',
            ], 404);
        }
    }

ルーティングの設定

特定のURLにアクセスした際に先程作ったコントローラーの特定のメソッドを実行するようにルーティング設定を行います。

routesというフォルダの中にapi.php, channels.php, console.php, web.phpがあると思います。

api.phpAPIでリクエストされたURLに対してルーティングを定義するファイルです。
channels.phpブロードキャストチャンネルのためのルーティングです。
console.phpコンソールプログラムのためのルーティングです。
web.phpWebページのルーティングを定義するファイルです。
ルーティングファイルと機能

今回はRESTAPIなのでapi.phpにルーティングの設定を記述していきます。

一般的なルーティング設定はGETPOSTなどHTTPメソッドごとに設定します。

use App\Http\Controllers\CalendarController;

Route::get('/calendars', [CalendarController::class, 'index']);
Route::post('/calendars', [CalendarController::class, 'store']);
Route::get('/calendars/{calendar}', [CalendarController::class, 'show']);
Route::put('/calendars/{calendar}', [CalendarController::class, 'update']);
Route::delete('/calendars/{calendar}', [CalendarController::class, 'destroy']);

しかし先程述べた通り、コントローラーを雛形通りに実装するとRoute::apiResourceを使うことでHTTPメソッドごとにルーティング設定しなくても、上記と同じプログラム通りに自動でルーティングを設定してくれます。

Route::apiResource('/calendars', 'App\Http\Controllers\CalendarController');

最終的なプログラムはこのようになります。

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});


Route::apiResource('/calendars', 'App\Http\Controllers\CalendarController');

最後にルーティング設定が正しく出来ているかのartisanのrouteコマンドで確認します。

php artisan route:list

ターミナルでこのような表が確認出来たらルーティング設定は完了です。

RESTAPIの動作確認

api.phpに記述したルーティングは初めから/apiというプレフィックスがURLに付与されています。(※設定ファイルを変更すれば/api以外にも出来る)

なので、/api/[パス]という形でapiにアクセスします。

試しに開発サーバを起動して、Postmanなどでlocalhost:8000/api/calendarsなどにリクエストして全てのカレンダー情報が取得したり登録が出来たらRESTAPIは完成です。

次回は認証システムの作成について説明していきます。