【Laravel】リソースAPIが動作しないときの対処法

laravel Laravel

LaravelにはリソースAPIと呼ばれる機能が搭載されています。CRUDを提供するAPIをartisanコマンドひとつで作成できるという機能です。

ところが、どう頑張ってもAPIが正常に動作しないという問題に直面しました。どうしてもIDを指定してオブジェクトを返してくれる「show」が動作しないのです。ほかのメソッドは動作するのに。。今回はガチで困りまして、解決までに3時間もかかってしまいましたので、解決法をメモしておきます。

スポンサーリンク

症状

artisanコマンドを使って、モデル・マイグレーション・リソースを作成しました。

php artisan make:model -mr PostCollection

通常通り、showメソッドでオブジェクトを返すように設定してみました。

/**
 * Display the specified resource.
 *
 * @param  \App\PostCollection  $postCollection
 * @return \Illuminate\Http\Response
 */
public function show(PostCollection $postCollection)
{
    return $postCollection;
}

しかし、なぜか空配列[]しか帰ってきません。

ルート・マイグレーション・モデルの作成はうまく行っています。storeは動作しており、データの登録は問題なく行えます。Tinkerでテストしてみると、データを取得できます。

しかし、showだけが動かない。ついでにeditも動作しません。つまり、本来自動的に取得できるはずのオブジェクト(ここでは$postCollection)がなぜか取得できない状況が起こりました。

スポンサーリンク

原因はルーティングのパスにあった

実は原因はルーティングのパスにありました。

問題解決前のルートがこちらです。route/api.phpに以下のように記載していました。

Route::resource('postcollection', "PostCollectionController");

解決後はこちら。

Route::resource('postCollection', "PostCollectionController");

違いが分かりますでしょうか?そうです。キャメルケースにしていなかったのが原因でした。

Route::resource('postCollection', "PostCollectionController");

実はRoute::resourceのパスに関しては、完全に自由だと思いこんでいたのです。モデル名はコントローラーの名前から自動的に取得され、モデルの取得もうまくいくと思っていました。

しかし、実はそうではないのです。APIに該当するモデルの選択はルート、つまりパスで行われているのです

モデル名の推測に関しては、LaravelのドキュメントのRoute Model Bindingに記載されていました。

ルーティング 5.7 Laravel

Implicit Binding
Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name. For example:

Route::get(‘api/users/{user}’, function (App\User $user) {
return $user->email;
});
Since the $user variable is type-hinted as the App\User Eloquent model and the variable name matches the {user} URI segment, Laravel will automatically inject the model instance that has an ID matching the corresponding value from the request URI. If a matching model instance is not found in the database, a 404 HTTP response will automatically be generated.

つまり、

  • 変数の名前はEloquentモデルの名前から自動的に生成される
  • どのインスタンスを生成するかは、リクエストURIから自動的に選択される

というわけです。なので、APIのURIはちゃんとキャメルケースで書かないとダメなわけです。クラスでモデルをuseしていたとしても、URIもきちんとルール通りに指定しないといけないのです。

引数の名前も要注意

さらにリソースコントローラーを利用するときは、引数の名前もルールに従う必要があります。

public function show(Post $post)
{
        return $post;
}

$postを$hogeなどとほかの文字列に勝手に変えてしまうと、うまく取得できなくなります。

こちらもキャメルケースでルールに則ってコーディングする必要があります。モデル名を変更した際などは要注意です。

パスに複合語を使うときはキャメルケースを厳守!

リソースAPIを使うときは、きちんとURIを定義しましょう。複合語はキャメルケースを厳守しましょう。

今までMemoやNoteなど1語で表現できるルーティングばかり使っていたため気づきませんでした。ちゃんとドキュメントには書いてあったのですが、正直ここまで読んでなかったです(T_T)

これを読んでいたら3時間無駄にせずに済んだのに(T_T)
ドキュメントはちゃんと読もう!

コメント

タイトルとURLをコピーしました