使用環境
Laravel 5.7
jwt-auth 1.0.0-rc3
この記事は下記の続きです。
Laravel + JWTAuth + Vue.js でAPIログイン認証の実装
Laravel + Vue.js にVuexを導入する
データベースの作成
データベースを作成するためマイグレーションファイルを作成します。
artisanで雛形を作成して、
$ php artisan make:migration create_tasks_table
スキーマは下記のようにします。
database/migrations/0000_00_00_000000_create_tasks_table.php
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateTasksTable extends Migration { public function up() { Schema::create('tasks', function (Blueprint $table) { $table->increments('id'); $table->string('title'); $table->integer('state_id')->unsigned()->default(1); $table->integer('user_id')->references('id')->on('users')->unsigned()->index()->nullable(); $table->timestamp('due_at')->nullable()->comment('期日'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('tasks'); } }
シーダーもartisanで雛形を作成して、
$ php artisan make:seeder TasksTableSeeder
ダミーデータを適当に作成します。
database/seeds/TasksTableSeeder.php
<?php use Illuminate\Database\Seeder; class TasksTableSeeder extends Seeder { public function run() { DB::table('tasks')->insert([ [ 'title' => 'はじめてのタスク', 'state_id' => 1, 'user_id' => 1, 'due_at' => '2018-10-02 14:28:19', 'created_at' => '2018-10-02 14:28:19', 'updated_at' => '2018-10-02 14:28:19' ],[ 'title' => '2番目のタスク', 'state_id' => 2, 'user_id' => 1, 'due_at' => '', 'created_at' => '2018-10-04 14:28:19', 'updated_at' => '2018-10-04 14:28:19' ] ]); } }
DatabaseSeeder.php
に作成したシーダーを追記します。
database/seeds/DatabaseSeeder.php
public function run() { $this->call(UsersTableSeeder::class); $this->call(TasksTableSeeder::class); }
artisanでデータベーステーブルを作成しましょう。
$ php artisan migrate $ php artisan db:seed --class=TaskTableSeeder
モデルの作成
Taskモデルを作成します。
$ php artisan make:model Models\Task
app/Models/Task.php
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Task extends Model { /** * @var array */ protected $fillable = [ 'title', 'state_id', 'user_id', 'due_at' ]; }
リポジトリの作成
モデルとコントローラーの間にリポジトリを挟んでみます。
あとで変えるかもですが、とりあえずこんな感じ。
app/Repositories/Repository.php
<?php namespace App\Repositories; use Illuminate\Database\Eloquent\Model; class Repository { /** * @var Model */ protected $model; /** * @param Model $model */ public function __construct(Model $model) { $this->model = $model; } /** * @return \Illuminate\Database\Eloquent\Collection */ public function all() { return $this->model->all(); } /** * @param array $data * @return mixed */ public function store(array $data) { return $this->model->create($data); } /** * @param array $data * @param int $id * @return mixed */ public function update(array $data, int $id) { $record = $this->model->find($id); return $record->update($data); } /** * @param int $id * @return int */ public function delete(int $id) { return $this->model->destroy($id); } /** * @param int $id * @return mixed */ public function findById(int $id) { return $this->model->findOrFail($id); } }
リクエストの作成
バリデーションの設定とかをここで書きます。
とりあえずタイトルを必須に。
app/Repositories/Repository.php
<?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class TaskRequest extends FormRequest { /** * @return bool */ public function authorize() { return true; } /** * @return array */ public function rules() { return [ 'title' => 'required' ]; } /** * @return array */ public function messages() { return [ 'title.required' => 'タイトルは必ず入力してください。', ]; } }
コントローラーの作成
コントローラーは基本response()->json()
で返します。
LaravelでViewを持つ必要がないので、CreateとEditはいらないですね。
app/Http/Controllers/TasksController.php
<?php namespace App\Http\Controllers; use App\Models\Task; use App\Repositories\Repository; use App\Http\Requests\TaskRequest; class TasksController extends Controller { /** @var Repository */ protected $repository; /** * TasksController constructor. * @param Task $task */ public function __construct(Task $task) { $this->repository = new Repository($task); } /** * @return \Illuminate\Http\JsonResponse */ public function index() { $tasks = $this->repository->all(); return response()->json($tasks); } /** * @param $id * @return \Illuminate\Http\JsonResponse */ public function show($id) { return response()->json($this->repository->findById($id)); } /** * @param TaskRequest $request * @return \Illuminate\Http\JsonResponse */ public function store(TaskRequest $request) { $response = $this->repository->store($request->all()); return response()->json($response, 201); } /** * @return \Illuminate\Http\JsonResponse */ public function update(TaskRequest $request, int $id) { $response = $this->repository->update($request->all(), $id); return response()->json($response, 200); } /** * @param $id * @return int */ public function destroy($id) { return $this->repository->delete($id); } }
ルーターの追記
作成したコントーラーにアクセスする為にルーターに追記します。
ログインしないとアクセスできないようにする為、auth:api
の中に書きます。
routes/api.php
<?php Route::group(['middleware' => 'auth:api'], function () { Route::get('/me', 'AuthController@me'); Route::post('/logout', 'AuthController@logout'); // Task Route::resource('tasks', 'TasksController', ['only' => ['index', 'show', 'store', 'update', 'destroy']] ); });
テストファイルの作成
最後に作成したAPIが問題なく動くか簡単にテストしてみます。
Laravelのテスト環境の構築は下記を参考にしてください。
LaravelのUnitTestでテスト時はデータベースを切り替える
このAPIはすべてログインしないと使用できないので、setUp
のactingAs
でログイン状態になるように指定します。
あとはシーダーも実行しておきましょう。
routes/api.php
<?php namespace Tests\Feature; use Tests\TestCase; use Illuminate\Foundation\Testing\RefreshDatabase; use App\User; class TaskTest extends TestCase { use RefreshDatabase; public function setUp() { parent::setUp(); $this->artisan('db:seed'); // ログイン認証 $user = factory(User::class)->create(); $this->actingAs($user, 'api'); } /** * @test */ public function GETでアクセスするとjsonが返却() { $response = $this->get('api/tasks'); $this->assertThat($response->content(), $this->isJson()); } /** * @test */ public function SHOWで取得情報は正しいか() { $response = $this->get('api/tasks/1'); $response->assertJson([ 'title' => 'はじめてのタスク' ])->assertStatus(200); } /** * @test */ public function GETで取得できるjsonは要件通りである() { $response = $this->get('api/tasks'); $tasks = $response->json(); $task = $tasks[0]; $this->assertSame(['id', 'title', 'state_id', 'user_id', 'due_at', 'created_at', 'updated_at'], array_keys($task)); } /** * @test */ public function GETの取得件数は2件である() { $response = $this->get('api/tasks'); $response->assertJsonCount(2); } /** * @test */ public function POSTでデータが追加される() { $params = [ 'title' => 'テストタイトル', 'state_id' => '1', 'user_id' => '1' ]; $this->postJson('api/tasks', $params); $this->assertDatabaseHas('tasks', $params); } /** * @test */ public function POSTでtitleが未入力のエラー() { $params = [ 'state_id' => '2', 'user_id' => '2' ]; $response = $this->postJson('api/tasks', $params); $response->assertJsonFragment(['title' => ['タイトルは必ず入力してください。']]); } /** * @test */ public function UPDATEで情報は更新されるか() { $params = [ 'title' => '書き換えたタイトル' ]; $respose = $this->putJson('api/tasks/1', $params); $this->assertTrue($respose->json()); $this->assertDatabaseHas('tasks', $params); } /** * @test */ public function DALETEで情報は削除されるか() { $params = [ 'id' => 1 ]; $this->deleteJson('api/tasks/1'); $this->assertDatabaseMissing('tasks', $params); } }
以上でAPIの実装は終わりです。
次回はVue.jsで実際に操作できるようにしていきたいと思います。
ここまでのソースコードはGithubに載せてあります。
LaravelTodoSPA
PHPフレームワーク Laravel Webアプリケーション開発 バージョン5.5 LTS対応