laravel5.7のカスタムバリデーションでエラーメッセージを出す

まず公式ドキュメントのバリデーションを見てみましょう。
https://readouble.com/laravel/5.7/ja/validation.html

*.blade.phpを作ります。

@extends('layouts.account')
@section('title', '原稿管理会社登録')

@section('breadcrumb')
	@@parent
	<ul class="breadcrumb">
      <li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb" >
        <a href="/top" itemprop="url">
          <span itemprop="title">ホーム</span>
        </a>
      </li>
      <li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb" >
        <a href="/top" itemprop="url">
          <span itemprop="title">原稿管理会社登録</span>
        </a>
      </li>
    </ul>
@endsection

@section('content')
<h2>原稿管理会社登録</h2>
      <hr>
      <form action="/company/confirm" method="post" id="form1">
      <table id="tbl">
        @csrf        
        <tr>
          <th>会社名</th><td><input type="text" name="company_name" size="40"  value="{{ old('company_name') }}">{{$errors->first('company_name')}}</td>
        </tr>
        <tr>
          <th>代理店</th><td><input type="text" name="agent_name" size="40"  value="{{ old('agent_name') }}">{{$errors->first('agent_name')}}</td>
        </tr>
      </table>      

      <div class="button_wrapper remodal-bg">
         <button type="submit" value="送信" id="square_btn" onClick="location.href='#modal'">登録</button>
      </div>
      </form>

      <!-- remodal -->
      <div class="remodal" data-remodal-id="modal">
        <button data-remodal-action="close" class="remodal-close"></button>
        <h1>登録しますか</h1>
        <p>
          入力した内容で宜しいでしょうか?
        </p>
        <br>
        <button data-remodal-action="cancel" class="remodal-cancel">Cancel</button>
        <button data-remodal-action="confirm" class="remodal-confirm">OK</button>
      </div>
@endsection

で、どうするか?
→ フォームリクエストを使う。

Laravel5.7 でバリデーションメッセージを表示する

Laravel5.7 でバリデーションメッセージを表示したいと思います。

Controllerの編集
まずformの確認画面のcontrollerで、送られてきたリクエストに対し、’required’として入力必須にします。

class CompanyConfirmController extends Controller
{
    public function confirm(Request $request){
    	$validatedData = $request->validate([
            'company_name' => 'required',
            'agent_name' => 'required',
        ]);
    	$confirm = new Company($request->all());

    	return view('companyconfirm', compact('confirm'));
    }
}

View(*.blade.php)の編集
デフォルトのメッセージを表示させます。

<span>{{$errors->first('company_name')}}</span>
<span>{{$errors->first('agent_name')}}</span>

特にメッセージをカスタマイズしなければ、英語のメッセージが表示されます。
これでもいいような気はします。

Laravel5.7 バリデーションエラー表示

まず公式を見ます。
https://readouble.com/laravel/5.7/ja/validation.html

リクエストの入力が指定したバリデーションルールに当てはまらなかった場合はどうなるか?
→自動的にユーザを以前のページへリダイレクトする。加えて、バリデーションエラーは自動的にフラッシュデータとしてセッションへ保存される。

ん?フラッシュデータって何?
>セッションにアイテムを保存したいことは良くあります。flashメソッドを使ってください。flashメソッドは直後のHTTPリクエストの間だけセッションにデータを保存します。それ以降は削除されます

なるほど、セッションに保持されるデータのことね。$errors変数はIlluminate\Support\MessageBagのインスタンス

う、う、急激に眠くなってきた。

続けて、エラー表示の例
$errors->all()で表示しています。

<h1>ポスト作成</h1>

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

Laravel5.7 バリデーションの種類

Laravel5.7のバリデーションにはどんなものがあるのか?
Webの記事を見ていてもよくわからない。。

ということで、公式ドキュメントを読み進めて行きたいと思います。
https://readouble.com/laravel/5.7/ja/validation.html

– イントロダクション
ValidatesRequestsトレイトをデフォルトで使用
→ なんじゃそりゃ? とりあえず、phpのマニュアルを見てみよう。凄いな、ループだ。キリがないな。 

トレイトは、PHP のような単一継承言語でコードを再利用するための仕組みのひとつです。 トレイトは、単一継承の制約を減らすために作られたもので、 いくつかのメソッド群を異なるクラス階層にある独立したクラスで再利用できるようにします。

トレイトの例
http://php.net/manual/ja/language.oop5.traits.php

trait ezcReflectionReturnInfo {
    function getReturnType() { /*1*/ }
    function getReturnDescription() { /*2*/ }
}

class ezcReflectionMethod extends ReflectionMethod {
    use ezcReflectionReturnInfo;
    /* ... */
}

class ezcReflectionFunction extends ReflectionFunction {
    use ezcReflectionReturnInfo;
    /* ... */
}

バリデーションに戻ります。
1.ルート定義
ここは想定通り。

Route::get('post/create', 'PostController@create');
Route::post('post', 'PostController@store');

コントローラ作成
getとstoreのメソッドを書いています。これも想定通り。

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class PostController extends Controller
{
    public function create()
    {
        return view('post.create');
    }
    public function store(Request $request)
    {
    }
}

バリデーションロジック
Illuminate\Http\Requestオブジェクトが提供する、validateメソッドを使用する。バリデーションに失敗すると、例外が投げられ、ユーザーに対し自動的に適切なエラーレスポンスが返される。
公式ドキュメントの例

public function store(Request $request)
{
    $validatedData = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);
}

最初のバリデーション失敗時に停止

$request->validate([
    'title' => 'bail|required|unique:posts|max:255',
    'body' => 'required',
]);

とりあえず、ここまででやってみましょうか。

public function store(Request $request){
        $request->validate([
            'company_name' => 'required',
            'agent_name' => 'required',
        ]);
    	$company = new Company([
    		'company_name' => $request->get('company_name'),
    	]);
    	$company->save();
    	$agent_mst = new Agent_mst([
    		'agent_name' => $request->get('agent_name'),
    	]);
    	$agent_mst->save();
    	$data = new Company();
        $table = $data::all();
        return view('companyindex', ['data'=> $table]);
    }

OK!!!
ただバリデーションエラー表示がこれだと、エラー時に何も表示されません。エラー表示を出すようにしましょう。

Laravel 5.7 フォームの確認画面へ遷移

フォームへの確認画面の流れとしては、一度確認画面にpostする値を経由してmysqlにinsertします。
大まかな流れは以下の通り。
(1)web/views/*.blade.php でフォーム入力
(2)routes/web.php で確認画面(ConfirmController)へpostする
(3)確認画面のControllerで、確認画面の.blade.php に値を渡す
(4)確認画面から route, controller, model 経由でinsertする

ブレイクダウンして順を追ってみていきましょう。

(1)web/views/*.blade.php でフォーム入力
companyindex.blade.php
「会社名」「代理店」がinput formです。formのactionは action=”/company/confirm” として確認画面に飛ばします。

<form action="/company/confirm" method="post" id="form1">
      <table id="tbl">
        @csrf        
        <tr>
          <th>会社名</th><td><input type="text" name="company_name" size="40"  value=""></td>
        </tr>
        <tr>
          <th>代理店</th><td><input type="text" name="agent_name" size="40"  value=""></td>
        </tr>
      </table>      

      <div class="button_wrapper remodal-bg">
         <button type="submit" value="送信" id="square_btn" onClick="location.href='#modal'">登録</button>
      </div>
      </form>

(2)routes/web.php で確認画面(ConfirmController)へpostする
formの入力画面は get、確認画面 confirm へと入力完了は post

Route::get('/company/input', 'CompanyInputController@input');
Route::post('/company/confirm', 'CompanyConfirmController@confirm');
Route::post('/company/index', 'CompanyIndexController@index');

(3)確認画面のControllerで、確認画面の.blade.php に値を渡す
わたってきた値を $request->all()で変数に代入して、confirmに渡します。

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Company;
use App\Agent_mst;

class CompanyConfirmController extends Controller
{
    public function confirm(Request $request){

    	$confirm = new Company($request->all());

    	return view('companyconfirm', compact('confirm'));
    }
}

(4)確認画面から route, controller, model 経由でinsertする
conmapnyconfirm.blade.php
hiddenで渡さないと駄目ですね。

<form action="/company/index" method="post" id="form1">
      <table id="tbl">
        @csrf        
        <tr>
          <th>会社名</th><td>{{$confirm->company_name}}</td>
        </tr>
        <tr>
          <th>代理店</th><td>{{$confirm->agent_name}}</td>
        </tr>
      </table>      

      <div class="button_wrapper remodal-bg">
         <button type="submit" value="送信" id="square_btn" onClick="location.href='#modal'">登録</button>
      </div>
      <input type="hidden" name="company_name" value="{{$confirm->company_name}}">
      <input type="hidden" name="agent_name" value="{{$confirm->agent_name}}">
      </form>

(4)確認画面から route, controller, model 経由でinsertする
これで、mysql側に入っているか確認します。

簡単やないかー

Larave5.7で複数テーブルにインサート

複数テーブルにインサートするにはどうすればいいか?
controllerで、それぞれテーブルごとのmodelにpostされた値を渡せばよいです。
CompanyとAgent_mstのmodelを読み込んで、requestを渡してsave(インサート)しています。

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Company;
use App\Agent_mst;

class CompanyIndexController extends Controller
{
    public function index(){
    	$data = new Company();
    	$table = $data::all();
    	return view('companyindex', ['data'=> $table]);
    }

    public function store(Request $request){
    	$company = new Company([
    		'company_name' => $request->get('company_name'),
    	]);
    	$company->save();
    	$agent_mst = new Agent_mst([
    		'agent_name' => $request->get('agent_name'),
    	]);
    	$agent_mst->save();
    	$data = new Company();
        $table = $data::all();
        return view('companyindex', ['data'=> $table]);
    }
}

出発

Laravel 5.7 フォーム(form)からPostする

Laravel 5.7でフォームからPostしてみます。
まず、resources/views配下の*.blade.phpから編集していきます。
formのactionは、そのまま、遷移先のパスを指定します。
例えば、topへの画面遷移なら action=”/top” となります。action=”account/index” としてしまうと、相対パスで遷移するので注意が必要。
@csrfを入れないをエラーが出るので注意が必要。

<form action="/account/index" method="post" id="form1">
      <table id="tbl">
        @csrf        
        <tr>
          <th>ログインID</th><td><input type="text" name="login_id" size="40"  value=""></td>
        </tr>
        <tr>
          <th>権限</th><td><input type="text" name="role" size="40" value="" v-model="message"></td>
        </tr>
        <tr v-if="message">
          <th>ほげ</th><td><div id="app"><input type="text" name="hoge" size="40" value="" ></div></td>
        </tr>
        <tr v-if="message">
          <th>ほげ</th><td><div id="app"><input type="text" name="hoge" size="40" value="" ></div></td>
        </tr>
        <tr v-if="message">
          <th>ほげ</th><td><div id="app"><input type="text" name="hoge" size="40" value="" ></div></td>
        </tr>
        <tr v-if="message">
          <th>ほげ</th><td><div id="app"><input type="text" name="hoge" size="40" value="" ></div></td>
        </tr>
      </table>      

      <div class="button_wrapper remodal-bg">
         <button type="submit" value="送信" id="square_btn" onClick="location.href='#modal'">登録</button>
      </div>
      </form>

つづいて、ルーティング
/routes/web.php を編集していきます。
formでpostする場合はRoute::postとします。http requestの場合はgetでした。

Route::post('/account/index', 'AccountController@store');

AccountController.php
App\AccountでモデルのAccount.phpを呼び出します。
上記で記載の通り、getの場合は public function index、postの場合はstore(Request $request)と書きます。

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Account;

class AccountController extends Controller
{
    //
    public function index(){
    	return view('account');
    }

    public function store(Request $request){
    	$account = new Account([
    		'login_id' => $request->get('login_id'),
    		'role' => $request->get('role'),
    		'hoge' => $request->get('hoge'),
    		'hoge' => $request->get('hoge'),
    		'hoge' => $request->get('hoge'),
    		'hoge' => $request->get('hoge')
    	]);
    	$account->save();
    	return view('account');
    }
}

Account.php
fillableでカラムを定義します。

class Account extends Model
{
    //
    protected $table = 'account';
    protected $fillable = [
    	'login_id',
    	'hoge',
    	'hoge',
    	'hoge',
    	'hoge',
    	'hoge'
    ];
}

select * from account;で、データが挿入されたか確認します。
OKのようです。割といけましたね。

insertでも読み込み($data::all();)でも、どちらもmodelを読み込んで、new hogeとクラスを作っているところは共通です。deleteとupdateはやってませんが、雰囲気は掴めてきたのではないでしょうか。

さて、次はどうするか?
まずinsertの仕組みを全部つくって、データを入れていって、その後、databaseからの読み込みでしょうか。ログイン、ページング、セッションなどはまだ先ですね。データの挿入のところかやっていきましょう。結構時間かかるなー

Laravel5.7でdbにinsertする方法

LaravelのEloquent ORMを使用するのであれば、controllerからinsertする。

まず公式ドキュメントを見てみましょう。

https://readouble.com/laravel/5.7/ja/eloquent.html
ページ中段の「モデルの追加と更新」
– Inserts
モデルから新しいレコードを作成するには新しいインスタンスを作成し、saveメソッドを呼び出す。

namespace App\Http\Controllers;

use App\Flight;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

Class FlightController extends Controller
{
	public function store(Request $request)
	{
		$flight = new Flight;
		$flight->name = $reqeust->name;
		$flight->save();
	}
}

HTTPリクエストのnameのパラメータをApp\Flightモデルのname属性に代入。saveメソッドが呼ばれると、レコードがDBに挿入とある。
namespaceを定義した後、use App\Flight;でFlightのmodelを呼び出しています。

Laravel5.7でcontorllerからmodelの呼び出し

mysqlにデータが入っており、controllerからmodelを呼び出してviewの*.blade.phpに表示させたい。

何をするか?こんなところでしょうか??(色々試していたら2日かかった)

1. mysqlにデータを入れる
2. modelから1で入れたテーブルを読み込む
3. controllerでmodelを読み込む
4. viewでmysqlのデータを表示する

1. mysqlにデータを入れる
まず、mysqlのtableにデータを挿入します。

INSERT INTO company(company_name, type, status) VALUES ('富士通', 1, 1),('リク ルート', 1, 1),('日本ユニシス', 1, 1);

2. modelから1で入れたテーブルを読み込む
app/Company.php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Company extends Model
{
    protected $table = 'company';
}

3. controllerでmodelを読み込む
use App\Company;でmodelを読み込みます。 App\Models\Company;だとエラーが出ます。ディレクトリがそのままと考えてよいでしょう。

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Company;

class CompanyIndexController extends Controller
{
    public function index(){
    	$data = new Company();
    	$table = $data::all();
    	return view('companyindex', ['data'=> $table]);
    }
}

4. viewでmysqlのデータを表示する
companyindex.blade.php
@foreachでcontrollerからpostする
$d->${カラム名}

@section('content')
      @foreach($data as $d)
      <li>{{$d->company_name}}</li>
      @endforeach
@endsection

反映されました。OK~~~~~~~~~~~~♪♪♪

さあ、次はbaldeからinputです。