使用環境
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対応


