Laravel(6.x)でREST APIの作り方

Laravelを使ってMVCモデルでView(Laravel標準ならBlade)も含めて
実装するサービスも多いと思いますが、
マイクロサービスといった言葉も流行ってきた昨今、データをAPIで
取得しView側はReact(Next)、Vue(Nuxt)、Angularといった
フロントエンドに特化したライブラリ・フレームワークを利用することが増えてきました
今回はAPI提供側としてのLaravelとして、LaravelでAPIを作る方法を
基本的な部分について紹介したいと思います

apiのルーティングを確認する

Webベースでこれまで作ってきた人はまずroutesの対象ファイルが違うことを
認識してください

Laravelではapiルーティングは routes/api.phpが対象です

artisanコマンドでCRUDベースで作成

ではまずはartisanコマンドを使ってapiのcontrollerファイルを作ってみましょう
APIはCRUDベースで作ることが多いので resourceオプションを付けて
実行してみます

php artisan make:controller UserController --resource

上記を実行すると、app/Http/Controllers配下にファイルが作成されます

ちなみにWebとApiが同じプロジェクトに共存していて
コントローラの管理場所を分けたい場合はフォルダ名もつけて

php artisan make:controller Api/UserController --resource

と実行することで Apiフォルダを作ってその配下に作成してくれます

作成された中身をみるとCRUD用にメソッドが用意されています
CRUDなのに4つじゃないの!?と思うかもしれませんので
わかりやすいように、「ユーザ」を操作するAPIと想定して説明します

メソッド名URLHttp Method内容
index/usersGET複数のユーザ取得
create/users/createGETユーザ作成表示
store/usersPOSTユーザを作成
show/users/{id}GET1件のユーザ取得
edit/users/{id}/editGETユーザ更新表示
update/users/{id}PUT/PATCH1件のユーザ更新
destroy/users/{id}DELETE1件のユーザ削除

{id}はユーザを一意に指定できるIDがURLパスに入ると考えてください
7つのメソッドで createedit の2つが実は View(画面)を返すように
想定されたメソッドとなっています
そのため、JSONなどをAPIのレスポンスと返すものを作りたい場合は
このcreateとeditのメソッドは不要となります

残った5つのうちindexshow が複数件のデータを取るか、1件のデータを
取るかの違いになっているのでどちらもCRUDの READ にあたります
あとは store は CREATE、update はUPDATE、 destroy はDELETEに
それぞれ当たります

ルーティングを設定する

routes/api.phpが対象とわかり、Controllerを作成したので
Controllerへのルーティングを設定しましょう
以下を記述してください

Route::resource('users', 'Api\UserController');

Route::resourceで /usersへの必要なパスがすべて用意してくれます

ルーティングを確認する

routesを増やしたのでルーティングを確認してみましょう

php artisan route:list
$ php artisan route:list
+--------+-----------+-----------------------+---------------+-------------------------------------------------+--------------+
| Domain | Method    | URI                   | Name          | Action                                          | Middleware   |
+--------+-----------+-----------------------+---------------+-------------------------------------------------+--------------+
|        | GET|HEAD  | /                     |               | Closure                                         | web          |
|        | GET|HEAD  | api/user              |               | Closure                                         | api,auth:api |
|        | GET|HEAD  | api/users             | users.index   | App\Http\Controllers\Api\UserController@index   | api          |
|        | POST      | api/users             | users.store   | App\Http\Controllers\Api\UserController@store   | api          |
|        | GET|HEAD  | api/users/create      | users.create  | App\Http\Controllers\Api\UserController@create  | api          |
|        | GET|HEAD  | api/users/{user}      | users.show    | App\Http\Controllers\Api\UserController@show    | api          |
|        | PUT|PATCH | api/users/{user}      | users.update  | App\Http\Controllers\Api\UserController@update  | api          |
|        | DELETE    | api/users/{user}      | users.destroy | App\Http\Controllers\Api\UserController@destroy | api          |
|        | GET|HEAD  | api/users/{user}/edit | users.edit    | App\Http\Controllers\Api\UserController@edit    | api          |
+--------+-----------+-----------------------+---------------+-------------------------------------------------+--------------+

ルーティングが追加されてることが確認できました
ただ、先程不要といったcreateeditについてもルーティングが追加されています
放置してもいいですが、余計なので外しておきましょう
先程のroutes/api.phpを以下のように書き換えてください

Route::resource('users', 'Api\UserController')->except(['create','edit']);

更新したら、再度ルーティングを確認してみましょう
そうするとcreateとeditのルーティングが除外されていると思います

$ php artisan route:list
+--------+-----------+------------------+---------------+-------------------------------------------------+--------------+
| Domain | Method    | URI              | Name          | Action                                          | Middleware   |
+--------+-----------+------------------+---------------+-------------------------------------------------+--------------+
|        | GET|HEAD  | /                |               | Closure                                         | web          |
|        | GET|HEAD  | api/user         |               | Closure                                         | api,auth:api |
|        | GET|HEAD  | api/users        | users.index   | App\Http\Controllers\Api\UserController@index   | api          |
|        | POST      | api/users        | users.store   | App\Http\Controllers\Api\UserController@store   | api          |
|        | GET|HEAD  | api/users/{user} | users.show    | App\Http\Controllers\Api\UserController@show    | api          |
|        | PUT|PATCH | api/users/{user} | users.update  | App\Http\Controllers\Api\UserController@update  | api          |
|        | DELETE    | api/users/{user} | users.destroy | App\Http\Controllers\Api\UserController@destroy | api          |
+--------+-----------+------------------+---------------+-------------------------------------------------+--------------+

データ取得を実装する

Controllerを作成し、ルーティングの設定も行ったので
実際にデータ取得(index)を実装してみましょう

まずはダミーデータを作成して返却してみます
indexの中身を以下のようにしてみましょう

    public function index()
    {
        $users = [
            ['id' => 1, 'name' => 'hoge'],
            ['id' => 2, 'name' => 'fuga'],
            ['id' => 3, 'name' => 'piyo'],
        ];
        return $users;
    }

2次元配列のデータを用意しました
ファイルを更新したらサーバを起動してブラウザからアクセスしてみます

php artisan serve

URL: http://localhost:8000/api/users

アクセスすると以下のように結果が返ってきたはずです

次に、MySQLのデータをModelをつかって取得し結果を返却してみます
MySQLの準備はここではコマンドのみ置いておくので説明は割愛します

mysql> create table users (id int, name varchar(10));
mysql> insert into users values (1,'hoge');
mysql> insert into users values (2,'fuga');
mysql> insert into users values (3,'piyo');
mysql> quit;

ModelについてはデフォルトのApp/User.phpを利用しておきます

Api/UserController.phpのindex()を以下のように修正します

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;

class UserController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $users = User::all();
        return $users;
    }

更新したら URLにアクセスしてみます
ダミーのときの同じ結果が返ってきたはずです

余談ですが、Modelをつかった場合はダミーのような配列ではなく
CollectionというクラスなのですがControllerの返却にセットするだけで
レスポンスをJson形式で返却してくれます

まとめ

簡単にですがLaravelでのREST APIの作り方を紹介しました
コマンドと少しの実装だけでリクエストルーティングから、
データの返却まで出来てしまうので非常に楽に導入できます