Posted at

LaravelのCRUDコード生成ツールを作って開発効率が爆上げした


作ったもの

LaravelのCRUDコード&Testコードをmigrationの項目から自動生成できるツールです。

【URL】

https://7k095m9l6q.csb.app/

【画面】

スクリーンショット 2019-08-12 20.28.57.png

 ↓

スクリーンショット 2019-08-12 20.26.22.png

以下の構成のコードが作れます。(具体的な内容は後で紹介)


  • Controller

  • Service

  • TestCase

▼おまけのコード


  • Vue.jsのsample

  • bladeのsample

  • Routing (API)のsample


利用シーン/メリット


  • CRUD処理の実装が簡単になる

  • Serviceクラスに実処理を書いてControllerを肥大化させないようにする

  • 自動生成なのでタイプミスによるバグがなくなる

  • UnitTestをして正しく動くことを確認できる

  • インストール不要、ブラウザからいつでも利用可能 (無料)

実際利用してから新規機能の開発効率が5倍くらい上がりました。


なぜ作ったのか

「早く、動くモノを作る」ためにどうしたらいいのかを考えた。

DB設計して、基本的なCRUDができるようになるための実装はルーティン作業だと気づいた。

【これまでの実装フロー】

①DB設計

 ↓

②migration作成

 ↓

③Modelクラス実装

 ↓

④Controller実装(create, get, update, delete..) ★

 ↓

⑤Service実装(create, get, update, delete..) ★

 ↓

⑥フロント実装(js, bladeなど)

 ↓

⑦テスト:データの取得→表示、新規作成や更新ができることを確認

 ↓

⑧バグを修正して仕上げる

一通り実装してからテストをすると、大抵どこかタイプミスがあったり、引数が間違っていたり、記述ミスがあったりしてエラーで動かないことが多い。

でもやろうとしていることは単純な処理なので、ここに時間を費やしてしまうのは時間のムダである。

データの項目名/型が違うだけで、あとは基本全て同じ動き(=実装)になる。

機械的に決まるコード(考えなくてもいいコード)なら自動化してしまえ!ということで、本ツールを作った。


どうやって作ったか

以下のFWと環境でオンライン上で完結させた。

FW : Vuetify.js

環境: codesandbox

>>完成コード

ロジックは文字の連結だけで済むのでjsが動けばよかった。

スタイルの調整とかも面倒なので、マテリアルデザインが内包されたVueのフレームワークである「Vuetify.js」を使ってみた。


開発期間

12時間くらいで完成(週末の合間に実装)


使い方

使い方はめちゃくちゃ簡単です。


  1. Model名を入力

  2. updateのキーを入力

  3. selectのキーを入力

入力前

スクリーンショット 2019-08-12 23.19.14.png

入力後

スクリーンショット 2019-08-12 23.20.39.png

4-1. カラムを入力

入力前

スクリーンショット 2019-08-12 23.20.46.png

入力後

スクリーンショット 2019-08-12 23.21.13.png

カラムは一個ずる入れるのは面倒ですよね。

migrationがすでにできてるから、そこから一発でバチン!と一括入力することもできます。

(1) migrationの項目定義部分をコピー

スクリーンショット 2019-08-12 23.27.37.png

(2) テキストエリア欄にペースト

スクリーンショット 2019-08-12 23.28.59.png

  ↓

スクリーンショット 2019-08-12 23.29.24.png

(3) CHECKボタンをクリック

id(increments)とtimestampsを除外して読み取ります

スクリーンショット 2019-08-12 23.30.24.png


生成されるコード


Controller

以下のコードができるので、COPYボタンでコピーしてControllerに貼り付けます

    private $postService;

public function __construct(PostService $postService)
{
$this->postService = $postService;
$this->middleware('auth');
}

public function createPost()
{
$this->middleware('auth');
// $user_id = Auth::user()->id; // if you need login userId
$user_id = request('userId');
$title = request('title');
$body = request('body');
$this->postService->createPost($user_id, $title, $body);
return ['code' => '200']; // TODO
}

public function updatePost()
{
$this->middleware('auth');
// $user_id = Auth::user()->id; // if you need login userId
$id = request('id');
$user_id = request('userId');
$title = request('title');
$body = request('body');
$this->postService->updatePost($id, $user_id, $title, $body);
return ['code' => '200']; // TODO
}

public function getPost($userId)
{
$data = $this->postService->getPost($userId);
return ['code' => '200', 'data' => $data]; // TODO
}


Service

同様にServiceクラスにコピペしましょう

public function createPost($user_id, $title, $body)

{
$model = new Post();
$model->user_id = $user_id;
$model->title = $title;
$model->body = $body;
$model->save();
return $model;
}

public function updatePost($id, $user_id, $title, $body)
{
$model = Post::updateOrCreate(
['id' => $id],
['user_id' => $user_id, 'title' => $title, 'body' => $body]);
return $model;
}

public function getPost($user_id)
{
$model = Post::where('user_id', $user_id)->first();
return $model;
}

その他実装点をNote:に書いているので忘れずに書きましょう。

スクリーンショット 2019-08-12 23.35.20.png


TestCase

artisanのmake:testでテストクラスを作ってそちらにコピペ。

$ php artisan make:test PostTest --unit

private $postService;

public function setUp()
{
$this->postService = new \App\Services\PostService();
parent::setUp();
}

public static function tearDownAfterClass()
{
Post::where('user_id', 99999)->delete();
}

public function testCreatePost()
{
$user_id = 9999; //**おかしなところはちょっと修正してください
$user_id = 10; //**おかしなところはちょっと修正してください
$title = 'This is title';
$body = 'This is body';

$result = $this->postService->createPost($user_id, $title, $body);
$model = Post::where('user_id', $user_id)->first();

$this->assertSame($model->user_id, $user_id);
$this->assertSame($model->title, $title);
$this->assertSame($model->body, $body);
}

public function testGetPost()
{
$user_id = 9999; //**おかしなところはちょっと修正してください
$user_id = 10; //**おかしなところはちょっと修正してください
$title = 'This is title';
$body = 'This is body';

$model = $this->postService->getPost($user_id);

$this->assertSame($model->user_id, $user_id);
$this->assertSame($model->title, $title);
$this->assertSame($model->body, $body);
}

public function testUpdatePost()
{
$id = 9999;
$user_id = 100;
$title = 'This is title[update]';
$body = 'This is body[update]';

$result = $this->postService->updatePost($id, $user_id, $title, $body);
$model = Post::where('user_id', $user_id)->first();

$this->assertSame($model->user_id, $user_id);
$this->assertSame($model->title, $title);
$this->assertSame($model->body, $body);
}

Note:も忘れずに

スクリーンショット 2019-08-12 23.40.36.png


おまけのコード


vue.js

スクリーンショット 2019-08-12 23.43.56.png


api.php (Routing)

スクリーンショット 2019-08-12 23.44.10.png

(deleteとupdate忘れた)


bladeとその他作業メモ

スクリーンショット 2019-08-12 23.44.26.png


ツール利用後の開発フロー

【これまでの実装フロー】

①DB設計

 ↓

②migration作成

 ↓

③Modelクラス作成

 ↓

④Controller/Service/TestCaseクラス作成

 ↓

⑤ツールを利用してコードをコピペ ★

 ↓

⑥テスト(1):Unitテストで動作検証(*ここで正常に動けばServiceクラスはOK) ★

 ↓

⑦フロント実装(js,bladeなど)

 ↓

⑧テスト(2):画面からの疎通確認できれば完了

 ↓

⑨バグを修正して仕上げる(基本バグは出ない)


終わりに

本ツールはあくまで自分の作業を簡単にするために作ったものなので、必ずしも他の人にも便利なものとは限らないです。

クラス設計とか構成がそもそも違うとか、思想が違うとかこだわりがそれぞれあると思うので、もし使えるなら使ってみてくださいというくらいです。

大事なことは「いかに作業時間を減らしつつ、品質を下げず、早くリリースするか」を考えて、自分の作業を簡単にするための外部のツールを導入してみたり、自分で開発してみたり、いろんな工夫をすることがプログラミング業務において重要なことだと思います。

Enjoy!!