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

# やりたいこと

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

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/117da090-3a21-8165-e02b-ae4d48bae598.png">

# 変更前のソースコード

```php5: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>
```
```php5:Request
    public function rules()
    {
        return [
            'name' => ['required', 'max:255'],
            'profile' => ['max:1000'],
        ];
    }
```
```php5: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に変換します。これにより、ルートとコントローラでのこれらの正規化について心配する必要がなくなります。

https://readouble.com/laravel/9.x/ja/requests.html

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

```php5: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を空文字に変換する場合

```diff_php: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() );
    }
```

:::note info
変更点１：null判定後空文字入力
```php
$request->input('profile') ?? '',
```
:::

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

chatGPTさんに聞いてみた。
![chatGDP_null_empty.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/fb6a6cd8-4bb1-79f5-3318-a988af77d370.png)


* **??演算子**
<img width="100%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/adadeda0-18b6-5da1-aaea-d9746cea78ee.png">


* **inputメソッド**
![chatGDP_input.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/ca96392a-aed6-b9b8-afdd-9e30f303894e.png)


:::note info
変更点２：onlyメソッドの削除
```php
update([
```
:::
![chatGDP_only.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1483743/8c3e5dea-e5d5-0608-c47b-e6a472c02d44.png)

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

onlyメソッドを使っている場合は、代入できない。
```php:間違い例
 $user->update($request->only([
            'name',
            'profile' => $request->input('profile') ?? '',
        ]));
```

### nullを許可したい場合

https://tech.amefure.com/php-laravel-blank-null

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


# 参考文献
* 公式ドキュメント

https://readouble.com/laravel/9.x/ja/requests.html

* nullを許可する場合

https://tech.amefure.com/php-laravel-blank-null

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

https://qiita.com/Yorinton/items/01363a28b28fa8f261f5