0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel】未入力のフォームをnullではなく空文字として送信したい

Posted at

やりたいこと

未入力の状態でフォームを送信したとき、空文字の値を入れたい

変更前のソースコード

edit.blade.php
  <form method="POST" action="{{ route('profile.update') }}">
    @csrf
    @method('patch')
    <div><label>名前:<input type="text" name="name" value="{{ $user->name }}"></label></div>
    <div>プロフィール:<br>
        <textarea name="profile" rows="10" cols="30">{{ $user->profile }}</textarea>
    </div>
    <input type="submit" value="更新">
  </form>
Request
    public function rules()
    {
        return [
            'name' => ['required', 'max:255'],
            'profile' => ['max:1000'],
        ];
    }
Controller
    public function update(ProfileRequest $request)
    {
        $user = \Auth::user();
        $user->update($request->only([
            'name',
            'profile',
        ]));
        session()->flash('success', 'プロフィールを編集しました。');
        return redirect()->route('users.show', \Auth::user() );
    }

不具合

未入力状態でフォームを送信すると
システムエラー(Column 'profile' cannot be null)が発生する。

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'profile' cannot be null (SQL: update users set profile = ?, users.updated_at = 2023-02-09 12:01:24 where id = 6)

なんか勝手にnullに変換されてるんですけど。。。

原因

Kernelクラスで空文字を自動でnullに変換しているみたい。

入力のトリムと正規化
デフォルトでは、LaravelはアプリケーションのグローバルミドルウェアスタックにApp\Http\Middleware\TrimStringsとIlluminate\Foundation\Http\Middleware\ConvertEmptyStringsToNullミドルウェアを含めています。これらのミドルウェアは、App\Http\Kernelクラスによってグローバルミドルウェアスタックにリストされています。これらのミドルウェアは、リクエストに応じてすべての受信文字列フィールドを自動的にトリミングし、空の文字列フィールドをnullに変換します。これにより、ルートとコントローラでのこれらの正規化について心配する必要がなくなります。

(参照:入力のトリムと正規化)

Kernel
    protected $middleware = [
        \App\Http\Middleware\TrustProxies::class,
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

犯人はあなたですね:point_right:「ConvertEmptyStringsToNull::class」

解決策

nullを空文字に変換する場合

Controller
    public function update(ProfileRequest $request)
    {
        $user = \Auth::user();
-       $user->update($request->only([
-           'name',
-           'profile',
-       ]));
+       $user->update([
+           'name' => $request->input('name'),
+           'profile' => $request->input('profile') ?? '',
+        ]);
        session()->flash('success', 'プロフィールを編集しました。');
        return redirect()->route('users.show', \Auth::user() );
    }

変更点1:null判定後空文字入力

$request->input('profile') ?? '',

requestで入力された文字が入力されていた場合、そのまま入力。
requestで入力された文字が未入力の場合、''(空文字)入力。

chatGPTさんに聞いてみた。
chatGDP_null_empty.PNG

  • ??演算子
  • inputメソッド
    chatGDP_input.PNG

変更点2:onlyメソッドの削除

update([

chatGDP_only.PNG

onlyメソッドは連想配列のキーと値がセットになって渡されるそう。
フォームの内容をそのまま渡さない場合は個別に指定してやる。

onlyメソッドを使っている場合は、代入できない。

間違い例
 $user->update($request->only([
            'name',
            'profile' => $request->input('profile') ?? '',
        ]));

nullを許可したい場合

まとめ

  • リクエストフォームが未入力の場合、自動でnullに変換される
  • 別にnullでもいい場合は、参照:https://tech.amefure.com/php-laravel-blank-null
  • nullを空文字として入力したい場合、??演算子を使う
  • onlyメソッドはキーと値をセットで渡す
  • フォームの内容をそのまま渡さない場合は個別に指定してやる
  • chatGPT半端ないって

参考文献

  • 公式ドキュメント

  • nullを許可する場合

  • 入力値が空かどうかの判別したい場合

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?