Believe you can

If you can dream it, you can do it.

LaravelでRESTfulAPIを作る〜その2〜

LaravelでAPIを作るの最終回です。MySQLとの接続を行っていきます。

Modelの作成

LaravelのORM、Eloquent(エロクアント)を使っていきます。
PHPが動いているDockerコンテナに入って artisan コマンドでModelを作ります。

$ docker-compose exec php bash
$ php artisan make:model Todos -f

App/Models 配下に Todos.php が作られます。

class Todos extends Model
{
    use HasFactory;
}
class TodosFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Todos::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            //
        ];
    }
}

調べていて気がついたのですが -c-r-api をつけることで Controllerも作ってくれるようです。
今回は -f オプションでモデルとファクトリを作成します。

Todosに追記

カラム情報とtimestampeがないことを定義します。

    protected $fillable = [
        'task',
    ];
    public $timestamps = false;

準備はこれで終わり。ControllerからModelを使ってDBアクセスをしてみます。

検索

Todos::all で全件を取得し、 Todos::find でプライマーキーで検索を行います。検索した結果をそのままレスポンスに返しています。
JSON_UNESCAPED_UNICODE はマルチバイト文字が文字化けを起こさないように設定しています。

    public function getTodos(Request $request): JsonResponse
    {
        $todos = Todos::all();
        return response()->json($todos, 200,
            ['Content-Type' => 'application/json;charset=UTF-8', 'Charset' => 'utf-8'],
            JSON_UNESCAPED_UNICODE);
    }

    public function getTodo(Request $request, int $id): JsonResponse
    {
        $todo = Todos::find($id);
        return response()->json($todo, 200,
            ['Content-Type' => 'application/json;charset=UTF-8', 'Charset' => 'utf-8'],
            JSON_UNESCAPED_UNICODE);
    }

登録、更新、削除

DB::beginTransactionトランザクションを開始し、成功時にはコミット、失敗時にはロールバックしています。
単一テーブルへの操作なので特に必要ないですが、お試しに入れてみました。Controllerにトランザクション処理があるのは正直気持ち悪さはありますがw

    public function createTodo(Request $request): JsonResponse
    {
        $task = $request->input('task');

        DB::beginTransaction();
        try {
            $new = Todos::create([
                'task' => $task,
            ]);
            DB::commit();
        } catch ($exception) {
            DB::rollBack();
        }

        return response()->json($new, 201,
            ['Content-Type' => 'application/json;charset=UTF-8', 'Charset' => 'utf-8'],
            JSON_UNESCAPED_UNICODE);
    }

    public function updateTodo(Request $request, int $id): JsonResponse
    {
        $task = $request->input('task');

        DB::beginTransaction();
        try {
            $todo = Todos::find($id);
            $todo->update(['task' => $task]);
            DB::commit();
        } catch ($exception) {
            DB::rollBack();
        }

        return response()->json($todo, 201,
            ['Content-Type' => 'application/json;charset=UTF-8', 'Charset' => 'utf-8'],
            JSON_UNESCAPED_UNICODE);
    }

    public function deleteTodo(Request $request, int $id): JsonResponse
    {
        DB::beginTransaction();
        try {
            $todo = Todos::find($id);
            $todo->delete();
            DB::commit();
        } catch ($exception) {
            DB::rollBack();
        }

        return response()->json(null, 200);
    }

まとめ

とりあえず目的のAPIを作ることはできました。検索はもっと複雑な絞り込みや結合を試さないとですし、ロジックをControllerに書いてしまっているのでソフトウェアアーキテクチャを導入して責務を明確にしてあげる必要がありますしユニットテストも書きたいし。まだまだやることはありますね。
それらについてはまだ後日余力があれば試したいと思います。
今回作ったソースはGitHubに上げてあります。

github.com