Help us understand the problem. What is going on with this article?

Laravel5.5でRequestを加工して保存する

経緯

ユーザーが入力した情報以外をDBに登録したり、
ユーザーが入力した情報を加工してDBに登録したりしたい時にはリクエストを上書きする方法があります
多分、ユーザーが入力した情報を加工することは、バグを生む原因になるのでよくないと思いますが、、
今回はその方法を解説していきます
他にはmergeinput hiddenとセッションを用いるなど様々な方法があると思います。
参考:
https://qiita.com/Fell/items/52be15196099f83ecdc7
以前作成した給与計算の例でみていきましょう

概要

まず給与計算には従業員名と、年月日、出勤時間、退勤時間、調整金額の入力する欄があるとします

スクリーンショット 2020-10-04 15.16.11.png
コードにするとこんな感じ

追加画面のコード

add.blade.php
@extends('layouts.app')
//ここはPWA化するためのセクション
@section('header')
    <link rel="manifest" href="../../../../manifest.json">
    <script>
        window.addEventListener('load', function() {
            if ('serviceWorker' in navigator) {
                navigator.serviceWorker.register("../../../../serviceWorker.js");
            }
        });
    </script>
@endsection
@section('content')
<div align='right'>
最終更新日{{ $now }}
</div>
<div align='center'>
<h4>勤怠入力はこちらから</h4>
{!! Form::open(['method' => 'post', 'route' => 'dailyPayment.add']) !!}
{{ Form::select('employee_id', ['従業員名' => $employee_option]) }}
<br>
{{ Form::selectYear('year', config('common.this_year') - 1, config('common.this_year'), config('common.this_year')) }}
//入力するのが営業終わりで昨日の日付分を入力するため、昨日の日付が先月末だった場合は月を先月まで戻す
@if ($lastDay == $yesterday)
{{ Form::selectRange('month', 1, 12, $lastMonth) }}
@else
{{ Form::selectRange('month', 1, 12, date('n')) }}
@endif
{{ Form::select('day', config('common.day'), $yesterday) }}
<br>
出勤時間
{{ Form::select('timeFrom', config('common.work_time'), config('common.timeFrom_default')) }}
退勤時間
{{ Form::select('timeTo', config('common.work_time'), config('common.timeTo_default')) }}
<br>
調整金額
{{ Form::number('adjustment', 0) }}
<br>
{{ Form::submit('追加する') }}
{{ Form::close() }}
</div>
<hr>
@endsection

ここでは時刻をH:iとしていますが、データベースに保存したいのはHiの時間でした。
そっちの方が給与の計算も時刻の計算も楽なので!
また時間の差分を.0.5で求めるようにしています
そこで以下のようにRequestデータを加工して、上書きすることで、書式を変更して保存することができます

dailyPaymentController.php
    public function store(StoreRequest $request)
    {
        $employee_id = $request->employee_id;
        $employee = $this->employee->findOrFail($employee_id);
        //勤怠情報の重複をチェック
        $exists_record = $this->dailyPayment->where('employee_id', $employee->id)->where('year', $request->year)->where('month', $request->month)->where('day', $request->day)->exists();
        //重複していた場合は削除ができる従業員のディテールページにリダイレクト
        if ($exists_record) redirect()->route('employee.detail', $employee->id)->with('error', $request->year . '年' . $request->month . '月' . $request->day . '日 ' . $employee->name . "の出勤情報は登録済みです\n削除してからお試しください");
        //ここでは:をとりのぞして文字列にしています
        $time_from = str_replace(':', '', $request->timeFrom);
        $time_to = str_replace(':', '', $request->timeTo);
        //ここで文字列として出勤時間と退勤時間を比較する
        if ($time_from > $time_to) return redirect()->back()>with('error', '不正な入力です');
        //22:00以降の出勤 つまり通常時間がない
        $normal_time = 0;
        $night_time = 0;
        if ($time_from >= '2201') {
            $night_time = $time_to - $time_from;
        //22:00以降を含む退勤
        } elseif ($time_to >= '2201') {
            $normal_time = 2200 - $time_from;
            $night_time = $time_to - 2200;
        //22:00以降の出勤も退勤も含まないので深夜料金がない
        } else {
            $normal_time = $time_to - $time_from;
        }

        //通常時間の端数が30の時、30を消して.5に変える
        if (preg_match('/30$/', $normal_time) || preg_match('/70$/', $normal_time)) {
            $normal_time = ($normal_time == 30) ? '0.5' : substr($normal_time, 0, -2) . '.5';
        //通常時間の端数が00の時、00を消して.0に変える
        } elseif (preg_match('/00$/', $normal_time)) {
            $normal_time = substr($normal_time, 0, -2) . '.0';
        }
        //深夜時間の端数が30の時、30を消して.5に変える
        if (preg_match('/30$/', $night_time) || preg_match('/70$/', $night_time)) {
            $night_time = ($night_time == 30) ? '0.5' : substr($night_time, 0, -2) . '.5';
        //深夜時間の端数が00の時、00を消して.0に変える
        } elseif (preg_match('/00$/', $night_time)) {
            $night_time = substr($night_time, 0, -2);
        }
        $day_total = $normal_time + $night_time * 1.25;
        /* NGコード
        $request->normal_time = $normal_time;
        $request->night_time = $night_time;
        $request->day_total = $day_total;
        $this->dailyPayment->fill($request->all())->save();
         */
        $this->dailyPayment->employee_id = $employee_id;
        $this->dailyPayment->year = $request->year;
        $this->dailyPayment->month = $request->month;
        $this->dailyPayment->day = $request->day;
        $this->dailyPayment->time_from = $request->time_from;
        $this->dailyPayment->time_to = $request->time_to;
        $this->dailyPayment->normal_time = $normal_time;
        $this->dailyPayment->night_time = $night_time;
        $this->dailyPayment->adjustment = $request->adjustment;
        $this->dailyPayment->day_total = $day_total;
        $this->dailyPayment->save();
        return redirect(route('employee.index'))->with('success', $employee->name . 'の勤怠情報を登録しました');
    }

このようにユーザーが入力したデータ以外も直接挿入することができる
たとえば、$this->dailyPayment->employee_id1にすれば、全員の労働が一人のものとなる
なお、コメントアウトに書いている通り

        $request->normal_time = $normal_time;
        $request->night_time = $night_time;
        $request->day_total = $day_total;
        $this->dailyPayment->fill($request->all())->save();

$request->all()を使うことはできない。

注意

この画面はadmin側のみ操作可能です
また、8時間以上働いた場合の増加分は計算しない仕様です。

satorunooshie
経済学を学んでいる大学三年生です PHP, Kotlinを中心に学習しています 役に立てそうな英語の記事や詰まったところを共有していきます
https://satorunooshie.net
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away