【Laravel8 api】バリデーションをFormRequestsに書いてみる。エラーはjsonで返す。

今回はLaravelのバリデーションをFormRequestに書いてみました。別クラスを作って作成するということですね。

簡単なCRUDを作ってそこでバリデーションをしていこうと思います。

ネットに上がっている記事は結構controllerに書いているものが多かったので別の方法を紹介します!

環境はLaravel8.xを想定しています!

バリデーションをcontrollerとは別に書くことで、cotroller自体がすっきり書くことができるので良いです!!!

それでは行ってみよーー (oノ´3`)ノ ピューーン!!

tableの作成

まずはテーブルを作っていきます。

今回はMemoっていうのを作っていきます。

php artisan make:model Memo -aCode language: CSS (css)

上記コマンドを使うことによってControllerやModelやmimgrationファイルとか必要なやつたくさん作ってくれます。

ほんで今回は簡単なテーブルをつくりますー

{app_name}/database/migrations/yyyy_mm_dd_xxxxxx_create_memos_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateMemosTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('memos', function (Blueprint $table) {
            $table->id();

            $table->string('title');
            $table->string('content');

            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('memos');
    }
}
Code language: HTML, XML (xml)
php artisan migrate

ほい、こんな感じでタイトルとコンテンツが入力できるようなやつ作成。

Modelを書く

一応modelも書いていく。

{app_name}/app/Models/Memo.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Memo extends Model
{
    //id以外は好きにinsert/updateができるように指定。(ブラックリスト方式)
    protected $guarded = ['id'];
    use HasFactory;
}
Code language: HTML, XML (xml)

ちなみに$guardedのほかには$fillableというのがありますが、それはホワイトリスト方式で好きにいじれるカラムを指定することができます。

今回は$guardedを使いますね~

カラム追加したときとかも対応しやすいんじゃないかなあと思ってます。

ほんなら先にバリデーション用のクラス作ってみます~

FormRequestの作成

ほい、今回はメモをcreateするという想定でやりましょうか。

createの為のバリデーションを書きますね。

php artisan make:request Memo/StoreMemoRequest

このコマンドでバリデーション用のクラスが作れます!

ほんでいじっていきます~

<?php

{app_name}/app/Http/Requests/Memo/StoreMemoRequest.php

namespace App\Http\Requests\Memo;

use Illuminate\Foundation\Http\FormRequest;

//---------------------------------------
//以下より追加
//---------------------------------------
use Illuminate\contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;

class StoreMemoRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        //ルーティングファイル、もしくはコントローラーで認証処理は行う前提なのでtrueで返す
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */

    //バリデーションルールの指定
    public function rules()
    {
        return [
            'title' => ['required', 'string', 'max:255'], //入力必須、文字列、最大255
            'content' => ['required', 'string', 'max:255'],
        ];
    }

    //validationでエラーがあった時のエラーメッセージを以下で生成する。
    public function messages()
    {
        return [
            'title.required' => 'タイトルを入力してください。', //入力が無かった場合のエラー文
            'content.required' => '内容を入力してください。',
        ];
    }

    //validationでエラーがでた時にjsonで返す。
    protected function failedValidation(Validator $validator)
    {
        $response = response()->json([
            'status' => 400, //jsonの返事の中身のエラー番号
            'errors' => $validator->errors(),
        ],400); //実際に送られるresponse codeが400番 これが無いと、jsonでエラーメッセージは返ってくるけど送れらてくるのは200番のstatusOKとくる。

        //例外を知らせる。
        //throw new 例外クラス名(例外message)
        throw new HttpResponseException($response);
    }
}
Code language: HTML, XML (xml)

ほい!これでOK。

あとはコントローラーを作っていくだけです!

その他のバリデーションルールの書き方例

//string型, email, 最大255, 自分は除いてuniqueにする。
'email' => ['string', 'email', 'max:255', Rule::unique('users')->ignore($this->id)],

//abilityテーブルのidの中に送られてきたリクエストは存在する。(実際のカラム名とリクエスト名が違うときに後ろで指定する。)
'ability_ids' => ['required', 'exists:abilities,id']

//usersテーブルの中にidはリクエストされたidは存在する。
'id' => ['required', 'exists:users'],Code language: PHP (php)

FormRequestを利用する場合には$thisを使っていますね。

自分自身を除くuniqueを利用するときは、編集作業を行う時などですね。

Controllerの作成

<?php

namespace App\Http\Controllers;

use App\Models\Memo;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

//---------------------------------------
//以下より追加
//---------------------------------------
use App\Http\Requests\Memo\StoreMemoRequest;

class MemoController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */

     //一応一覧表示機能も
    public function index()
    {
        return response()->json([
            'success' => true,
            'message' => 'List Success!',
            'details' => Memo::all()
        ]);
    }

    //先にバリデーションをするのでStoreMemoRequestから受け取った値を$request変数へ
    public function store(StoreMemoRequest $request)
    {
        //バリデーションで問題が無ければ保存
        Memo::create($request->all());
        return response()->json([
            'success' => true,
            'message' => 'Insert success!',
            'details' => $request->all()
        ]);
    }

}
Code language: HTML, XML (xml)

ほい!こんな感じですかね。

あ、api.phpを忘れていた。
ということで以下のように書いていきます。

{app_name}/routes/api.php
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\MemoController; //作成したMemoControllerを追加
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

//デフォルトで書いてあったやつ
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

//追加部分
//Resourceにする事でrestfulなroutingにこれだけで対応できる。
Route::Resource('memo', MemoController::class);Code language: HTML, XML (xml)

これでOKだ!

後はPOSTメソッドなのでpostmanを使って確認してみましょう。

postmanが良く分からない方は以下を見てみてくださいね。

【Postman】インストールと使い方【API実行ツール】

ほい、ほんならPOSTメソッドで送って本当に保存されるのか確認してみてください。

DBにPOSTMANから送信した値が入っていたら完成です!

あ、ちなみにapiを利用する際にはurlが変わって、今回の場合なら以下のようになります。

以下のpathにPOSTメソッドを投げてくださいね。

/api/memo

まとめ

バリデーションもこのように書いていけば、Controllerがすっきり書くことができますね。

FatControllerを避けるためにも意識していきたいところはたくさん。

1 COMMENT

【Laravel8】CRUD機能でfill($request->all())だとパスワードが平文で保存されてしまう。 - 東京初めてエンジニア へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA