laravel バリデーション実行前にpostされたデータを弄る

# 目的

- カスタムバリデーターのクラス内にメソッド追加してバリデーションが実行される前にpostされた値をいじる方法をまとめる

# 環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Big Sur(11.6) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.11 | Homebrewを用いてこちらの方法で導入→[Mac HomebrewでPHPをインストールする](https://qiita.com/miriwo/items/cd54077aad7e139cf518) |
| Laravel バージョン | 8.X | commposerを用いてこちらの方法で導入→[Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08) |
| MySQLバージョン | 8.0.21 for osx10.13 on x86_64 | Homebrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |

# ご注意

- 本知見は筆者が携わっているプロジェクトで一緒に仕事をさせていただいているチームメンバーの方からいただいた知見です。
    - 本当にありがとうございます！

# 概要

- 下記記事で実装した「laravel8_easy_crud」アプリのカスタムバリデーターのクラスをいじってpostされた値をバリデーションチェック前にいじってみる。
    - [https://qiita.com/miriwo/items/5d2483c4b0d25df33c2f](https://qiita.com/miriwo/items/5d2483c4b0d25df33c2f)
- 今回はpostされた値の末尾に数値「9999」を付与するように実装してみる。
    - この実装は特に意味はなく「バリデーション実行前にpostされたデータをいじる方法」を説明するために実装する。
- 今回お試しで実装したコードのリモートリポジトリは下記である。
    - [https://github.com/miriwo0104/laravel8_easy_crud/tree/add_value_to_post_data](https://github.com/miriwo0104/laravel8_easy_crud/tree/add_value_to_post_data)

# 方法

1. フォームリクエストクラスが記載されているファイルを開く。
1. 下記のように内容を修正してフォームリクエストクラスにprepareForValidation()メソッドを追加する。

    ```laravel8_easy_crud/app/Http/Requests/ContentRequest.php
    <?php
    
    namespace App\Http\Requests;
    
    use Illuminate\Foundation\Http\FormRequest;
    
    class ContentRequest extends FormRequest
    {
        /**
         * Determine if the user is authorized to make this request.
         *
         * @return bool
         */
        public function authorize()
        {
            return true;
        }
    
        /**
         * Get the validation rules that apply to the request.
         *
         * @return array
         */
        public function rules()
        {
            return [
                'content' => ['required', 'num-only'],
            ];
        }
    
        /**
         * バリーデーションのためにデータを準備
         *
         * @return void
         */    
        public function prepareForValidation() : void
        {
            // 入力された値の末尾にintの9999を付与する
            $this->replace([
                'content' => $this->input('content') . 9999,
            ]);
        }
    }
    ```

1. ちなみにフォームリクエストクラスで定義している`prepareForValidation()`メソッドは`laravel8_easy_crud/vendor/laravel/framework/src/Illuminate/Validation/ValidatesWhenResolvedTrait.php`ですでに定義されており、フォームリクエストクラスでオーバーライドしている。

    ```laravel8_easy_crud/vendor/laravel/framework/src/Illuminate/Validation/ValidatesWhenResolvedTrait.php
    /**
     * Prepare the data for validation.
     *
     * @return void
     */
    protected function prepareForValidation()
    {
        //
    }
```

1. `prepareForValidation()`メソッド内で使っている`merge()`メソッドなどは下記で定義されているものを呼んでいるっぽい。
    - `laravel8_easy_crud/vendor/laravel/framework/src/Illuminate/Http/Request.php`
    - `prepareForValidation()`メソッド内でよく使うのは下記3メソッドである。

        ```laravel8_easy_crud/vendor/laravel/framework/src/Illuminate/Http/Request.php
        /**
         * Merge new input into the current request's input array.
         *
         * @param  array  $input
         * @return $this
         */
        public function merge(array $input)
        {
            $this->getInputSource()->add($input);
        
            return $this;
        }
    
        /**
         * Replace the input for the current request.
         *
         * @param  array  $input
         * @return $this
         */
        public function replace(array $input)
        {
            $this->getInputSource()->replace($input);
        
            return $this;
        }
    
        /**
         * This method belongs to Symfony HttpFoundation and is not usually needed when using Laravel.
         *
         * Instead, you may use the "input" method.
         *
         * @param  string  $key
         * @param  mixed  $default
         * @return mixed
         */
        public function get(string $key, $default = null)
        {
            return parent::get($key, $default);
        }
        ```

1. `prepareForValidation()`メソッド内で使用できるメソッドの代表的なものを下記にまとめておく。
    1. `get('キー名')`もしくは`input('キー名')`
        1. htmlのinput要素のnameて定義したキーを指定してpostされた値を取得する。
        1. 呼び出し時の記載例
            - `$this->input('content')`
            - `$this->get('content')`
    1. `$this->replace(['キー名' => 格納したい値`])
        1. postされた既存のキーの値を書き換える。
        1. 呼び出し時の記載例
            
            ```php
            // 入力された値をすべてintの0000に置き換える
            $this->replace([
                'content' => '0000',
            ]);
            ```

    1. `$this->merge(['キー名' => 格納したい値`])
        1. postされた値にキーと値を追加する。
            1. 既存キーのあチアを変更したいわけではなく、新たにキーと値を増やしたい時に使う。
        1. 呼び出し時の記載例
            
            ```php
            // 入力された値をすべてintの0000に置き換える
            $this->merage([
                'name' => 'test',
            ]);
            // 上記のように記載してpostするとpostされたデータのキーにnameと値「test」も含まれている
            ```

    1. まとめ
        1. 呼び出し
            - `get('キー名')`
            - `input('キー名')`
        1. 既存キーに紐づくデータの更新
            - `$this->replace(['キー名' => 格納したい値`])
        1. 新規にキーと値を設定
            - `$this->merge(['キー名' => 格納したい値`])

# 参考文献

- [https://qiita.com/zdjjs/items/cd1c92f82f39a2475104](https://qiita.com/zdjjs/items/cd1c92f82f39a2475104)
- [https://readouble.com/laravel/6.x/ja/validation.html](https://readouble.com/laravel/6.x/ja/validation.html)
    - 「バリデーション前の入力準備」の記載部分