概要
画像ファイルを含むフォームの作り方、画像ファイルに対するバリデーションについて整理する。
アップロード画像処理~準備で枠組みを作った商品データのアプリケーションを加工していく。
一般的なアップロードファイルの入力・取得についてはこちらを参照。
入力・登録後のアップロード画像の登録・保存についてはこちらを参照。
ルーティング
通常のリソースベースでは、新規データの入力はcreateルートが想定されているが、ここではindexページに商品入力フォームを配置し、そこで商品データの内容や商品画像を入力する。
| 1 2 3 4 5 6 7 | +--------+----------+-------+-------------+-------------------------------------------+------------+ | Domain | Method   | URI   | Name        | Action                                    | Middleware | +--------+----------+-------+-------------+-------------------------------------------+------------+ ........ |        | GET|HEAD | items | items.index | App\Http\Controllers\ItemController@index | web        | ........ +--------+----------+-------+-------------+-------------------------------------------+------------+ | 
商品入力ページ~index.blade.php
indexページに商品入力フォームを配置し、そこに商品画像ファイルの選択要素を含める。画像選択を含むフォームに関する要点は以下のとおり。
- form要素に以下のオプションを加える- enctype="multipart/form-data"
 
- input要素でtype="file"を指定する
なおリソースベースによるデータ登録の場合、createアクションでルーティングされるページに入力フォームを置くことが想定されているが、ここでは商品一覧を表示するindexページで商品入力も行い、その入力フォームからstoreアクションを呼び出す。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <!DOCTYPE html> <html lang="ja" dir="ltr">   <head>     <meta charset="utf-8">     <title>商品一覧・入力</title>   </head>   <body>     <h1>商品一覧・入力</h1>     <form method="post" action="{{ route('items.store') }}" enctype="multipart/form-data">       @csrf       <div>         <input type="text" name="name" placeholder="商品名を入力">       </div>       <div>         <input type="number" name="price" placeholder="価格を入力">       </div>       <div>         <input type="file" name="image">       </div>       <input type="submit" value="商品登録">     </form>   </body> </html> | 
フォームリクエスト
フォームリクエストでバリデーションを行う。フォームリクエストItemRequestは以下のコマンドで作成。
| 1 2 | $ php artisan make:request ItemRequest Request created successfully. | 
生成されたフォームリクエストの雛形で、以下を編集。
- authorize()の戻り値を- trueに変更
- rules()の戻り値の配列にバリデーションルールを記述
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class ItemRequest extends FormRequest {     public function authorize()     {         return true;     }     public function rules()     {         return [             'name' => ['required'],             'price' => ['required', 'integer', 'min:0'],             'image' => ['file', 'mimes:jpeg,jpg,png',                         'dimensions:min_width=100,min_height=100,max_width=2000,max_height=2000'],         ];     } } | 
コントローラー~index/store
コントローラーでは2つのアクションメソッドを定義している。
- indexアクションでは- indexページを表示するのみ
- storeアクションでは、フォームデータに基づいて- Itemインスタンスをデータベースに登録- ただし現段階では、画像ファイルパスを格納するimageに、仮置きで空文字列''をセットしている。
- この変数へのファイルパスの設定は、別項のアップロード画像ファイルの保存・登録で実装する。
 
- ただし現段階では、画像ファイルパスを格納する
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?php namespace App\Http\Controllers; use App\Item; use Illuminate\Http\Request; use App\Http\Requests\ItemRequest; class ItemController extends Controller {     public function index()     {         return view('items.index');     }     public function store(ItemRequest $request)     {         // 商品をデータベースに登録         Item::create([             'name' => $request->name,             'price' => $request->price,             'image' => '',         ]);     } } | 
ここでの留意点は以下のとおり。
- 作成したフォームリクエストItemRequestをuseでインポートし、メソッドインジェクションをRequestからItemRequestに変更している
- create()メソッドがマスアサインメントのため、- Itemモデルで- $fillableの定義が必要
Itemモデルでの$fillable定義は以下の部分を追記。
| 1 2 3 4 5 6 7 8 9 10 | <?php namespace App; use Illuminate\Database\Eloquent\Model; class Item extends Model {     protected $fillable = ['name', 'price', 'image']; } | 
データ登録確認
この状況でアプリケーションを実行し、フォームでデータを登録したのが以下の例。
画像ファイルのパスは、まだ未登録の状態。
| 1 2 3 4 5 6 7 | mysql> select * from items; +----+-------+-------+-------+---------------------+---------------------+ | id | name  | price | image | created_at          | updated_at          | +----+-------+-------+-------+---------------------+---------------------+ |  1 | item1 |   100 |       | 2021-10-25 21:25:52 | 2021-10-25 21:25:52 | +----+-------+-------+-------+---------------------+---------------------+ 1 row in set (0.00 sec) |