LoginSignup
104
117

More than 5 years have passed since last update.

Laravelでの各Form要素でのValidationやエラー制御(のメモ)

Last updated at Posted at 2015-08-13

Laravelにかぎらず、いろいろなフレームワークにForm処理に関する便利機能がありますが、input textではうまく動くものでも、checkboxやfile処理とかだと結局使えず、むしろイライラすることありますね。。。

ここではいざというときに困らないようにFormの主要要素とLaravelのバリデーション、さらにはBootstrapとの組み合わせをまとめておきたいと思います。本当は、各バーツ毎にテストしたいのですが、とりあえずここでは全体をメモ。

やりたいこと

Laravel + Bootstrapを利用してFormデータのエラー処理パターンをまとめておきたい。

細かく書くと、

  • 正常時の値の受け取り(checkboxとか選択しないとそもそもnullのやつの扱いとかチェック)。
  • エラーの検知(Validation)。
  • エラー時の表示の整理(エラーメッセージの受け取り方、表示やスタイル変更制御)。
  • 入力値の保持方法(Laravelでは基本Input::old('hoge')の利用)。
  • checkboxやfile等のおろそかになりがちな要素との連携チェック。

あたりを整理しておきたい。

Formのビュー

formを表示するviewをviews/form.blade.phpとして作成。

エラー時にForm要素に対して、下記のようにエラーが出力されるようにする。
下記キャプチャは全てのエラーが出力されてた場合(ルールが複数設定されている要素は最初のエラーを表示)。

form

ポイントとしては、

  • <div class="form-group">で全体をくくれる要素はくくる
  • くくれない要素は、エラーメッセージだけをくくる
  • エラーの表示、クラスの変更は@if(!empty($errors.first('name'))) has-error @endifという感じで。
  • 値の維持は基本Input::old('name')で。
  • select,checkbox等は、@if(Input::old('name')=='name') selected @endifという感じで。

あたり。それを考慮した記述が下記。

共通レイアウト layout.blade.php

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
</head>
<body>

    <div class="container">
        @yield('content')
    </div>

<!-- js -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script>
    @yield('script')
</script>
</body>
</html>

肝心の中身。テスト用のform.blade.php。少々複雑ですが、とりあえず全ソースをペースト。

@extends('layout')

@section('content')

    <h1 style="margin-bottom:30px;">新規登録</h1>

    <!-- form -->
    <form method="post" action="/store" enctype="multipart/form-data">

        <!-- input type="text" string -->
         <div class="form-group @if(!empty($errors->first('name'))) has-error @endif">
            <label>名前</label>
            <input type="text" name="name" value="{{Input::old('name')}}" class="form-control">
            <span class="help-block">{{$errors->first('name')}}</span>
        </div>

        <!-- input type="text" string confirm -->
         <div class="form-group @if(!empty($errors->first('email'))) has-error @endif">
            <label>E-Mail</label>
            <input type="text" name="email" value="{{Input::old('email')}}" class="form-control">
            <span class="help-block">{{$errors->first('email')}}</span>
        </div>

        <div class="form-group @if(!empty($errors->first('email_confirmation'))) has-error @endif">
            <label>E-Mail(再入力)</label>
            <input type="text" name="email_confirmation" value="{{Input::old('email_confirmation')}}" class="form-control">
            <span class="help-block">{{$errors->first('email_confirmation')}}</span>
        </div>

        <!-- input type="text" int -->
         <div class="form-group @if(!empty($errors->first('age'))) has-error @endif">
            <label>年齢</label>
            <input type="text" name="age" value="{{Input::old('age')}}" class="form-control">
            <span class="help-block">{{$errors->first('age')}}</span>
        </div>

        <!-- select -->
         <div class="form-group @if(!empty($errors->first('area'))) has-error @endif">
            <label>エリア</label>
            <select name="area" class="form-control">
                <option value="">選択して下さい</option>
                <option value="option1" @if(Input::old('area')=="option1") selected @endif>オプション1</option>
                <option value="option2" @if(Input::old('area')=="option2") selected @endif>オプション2</option>
            </select>
            <span class="help-block">{{$errors->first('area')}}</span>
        </div>

        <!-- radio -->
        <p><b>性別</b></p>
        <div class="radio-inline">
            <label>
                <input type="radio" name="gender" value="man" @if(Input::old('gender')=="man") checked @endif></label>
        </div>
        <div class="radio-inline">
            <label>
                <input type="radio" name="gender" value="woman" @if(Input::old('gender')=="woman") checked @endif></label>
        </div>
         <div class="form-group @if(!empty($errors->first('gender'))) has-error @endif">
            <span class="help-block">{{$errors->first('gender')}}</span>
        </div>

        <!-- checkbox -->
        <p><b>告知メディア</b></p>
        <div class="checkbox">
            <label>
                {{-- <input type="hidden" name="media1" value="none"> --}}
                <input type="checkbox" name="media1" value="web" @if(Input::old('media1')=="web") checked @endif> Web
            </label>
        </div>
         <div class="form-group @if(!empty($errors->first('media1'))) has-error @endif">
            <span class="help-block">{{$errors->first('media1')}}</span>
        </div>

        <div class="checkbox">
            <label>
                {{-- <input type="hidden" name="media2" value="none"> --}}
                <input type="checkbox" name="media2" value="TV" @if(Input::old('media2')=="TV") checked @endif> TV
            </label>
        </div>
         <div class="form-group @if(!empty($errors->first('media2'))) has-error @endif">
            <span class="help-block">{{$errors->first('media2')}}</span>
        </div>


        <!-- textarea -->
         <div class="form-group @if(!empty($errors->first('note'))) has-error @endif">
            <label>感想</label>
            <textarea name="note" class="form-control" rows="3">{{Input::old('note')}}</textarea>
            <span class="help-block">{{$errors->first('note')}}</span>
        </div>

        <!-- file -->
         <div class="form-group @if(!empty($errors->first('image'))) has-error @endif">
            <label>画像</label>
            <input type="file" name="image">
            <span class="help-block">{{$errors->first('image')}}</span>
        </div>

        <!-- token -->
        <input type="hidden" name="_token" value="{{csrf_token()}}">

        <input type="submit" value="登録" class="btn btn-primary">

    </form>

@stop

コントローラ(バリデーション実行)

とりあえず、上記のエラー時表示をテストするためのもの。
formからの値を受け取りバリデート。NGならviewに戻し、OKならstore.blade.phpにリダイレクトし、受け取った内容を表示するものとする。ファイル名はFormController.phpとした。

コントローラーのコードは、Laravelのスマートな?Validation記述のお陰でそれほど複雑ではない。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;

class FormController extends Controller
{
    //
    public function form()
    {
        return view('form');
    }

    public function store(Request $request)
    {

        //inputs
        $inputs = $request->all();

        //rules
        $rules = [
            'name'=>'required|min:6|max:10',
            'email'=>'required|email|confirmed',
            'age'=>'required|numeric',
            'area'=>'required',
            'gender'=>'required',
            'media1'=>'required',
            'media2'=>'required',
            'note'=>'required|max:10',
            'image'=>'required|image|max:100', //kbyte
        ];

        //validation
        $validation = \Validator::make($inputs,$rules);

        //if fails
        if($validation->fails())
        {
            return redirect()->back()->withErrors($validation->errors())->withInput();
        }

        //バリデーションOK

        //fileは個別に処理
        $file = \Input::file('image');
        if(!empty($file))
        {
            $filename = $file->getClientOriginalName();
            $move = $file->move('./',$filename); //public
        }
        else
        {
            //ファイルアップロードが無いときは変数を初期化(viewでのエラー防止)
            $inputs["image"] = "none";
        }


        //
        return view('store',compact('inputs'));
    }
}

OKだったとき受け取った値を表示するビュー

バリデーションがOKなら、store.blade.phpにて値を表示。エラー時は、冒頭の画面が表示される。

form

ソースは、こんな感じ。ただ表示しているだけ。

@extends('layout')

@section('content')

    <h1>内容表示</h1>

    <div class="row">
        <div class="col-sm-12">
            <a href="/form" class="btn btn-primary" style="margin:20px;">フォームに戻る</a>
        </div>
    </div>

    <!-- table -->
    <table class="table table-striped">
        <tr><td>名前</td><td>{{$inputs["name"]}}</tr>
        <tr><td>E-Mail</td><td>{{$inputs["email"]}}</tr>
        <tr><td>年齢</td><td>{{$inputs["age"]}}</tr>
        <tr><td>エリア</td><td>{{$inputs["area"]}}</tr>
        <tr><td>性別</td><td>{{$inputs["gender"]}}</tr>
        <tr><td>メディア</td><td>{{$inputs["media1"]}}</tr>
        <tr><td>メディア</td><td>{{$inputs["media2"]}}</tr>
        <tr><td>感想</td><td>{{$inputs["note"]}}</tr>
        <tr><td>ファイル</td><td>{{$inputs["image"]}}</tr>
    </table>

@stop
104
117
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
104
117