前回までの状況はこちら。
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/diet-mng
データ入力ダイアログから入力データをデータベースに登録するところまで行きます。
モデル
class User extends Authenticatable
{
public function EatingManagements()
{
return $this->belongsToMany('App\Model\EatingManagement');
}
class EatingManagement extends Model
{
protected $table = 'eating_managements';
public function users()
{
return $this->belongsToMany('App\User');
}
public function timezones()
{
return $this->belongsToMany('App\Model\Timezone');
}
}
class Timezone extends Model
{
protected $table = 'timezones';
public function Eating()
{
return $this->belongsToMany('App\Model\EatingManagement');
}
}
リポジトリ
<?php
namespace App\Repository;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Model\EatingManagement;
use App\Model\Timezone;
use App\User;
class EatingManagementRepository
{
private $paramNames = ['date', 'item', 'protein', 'riqid', 'carbo', 'calorie'];
public function __construct()
{
}
public function add($param, $user, $timezone)
{
$model = new EatingManagement();
foreach($this->paramNames as $name)
{
$model->$name = $param[$name];
}
$model->save();
$time = Timezone::where('id', $timezone)->first();
$this->attachToUser($model, $user);
$this->attachToTimezone($model, $time);
}
public function attachToUser($model, $user)
{
$model->users()->attach($user);
}
public function detachToUser($model, $user)
{
$model->users()->detach($user);
}
public function attachToTimezone($model, $timezone)
{
$model->timezones()->attach($timezone);
}
public function detachToTimezone($model, $timezone)
{
$model->timezones()->detach($timezone);
}
public function getParam()
{
return $this->paramNames;
}
}
コントローラー
<?php
namespace App\Http\Controllers\Eating;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use App\Repository\EatingManagementRepository;
class ApiController extends Controller
{
public function __construct()
{
$this->middleware('auth');
$this->eatingManagement = new EatingManagementRepository();
}
/**
* データを1件登録する
*/
public function add(Request $request)
{
$paramNames = $this->eatingManagement->getParam();
$param = [];
foreach($paramNames as $name) {
$param[$name] = $request->contents[$name];
}
$this->eatingManagement->add($param, Auth::user(), $request->contents['timezone']);
return response()->json();
}
}
パラメータを設定する処理をちょっと変えています。
Vue側でtypoしていないことが前提ですが、なるべくコードの中で直値を使わない(定義する箇所は一か所のみ)ようにするための工夫。
これが正解なのか、いまだにわかりませんけどね。
Vue側の修正です。
EatingDashboardComponent.vue
<template>
<div>
<div class="dashboard">
<div class="chart">
<canvas id="eating"></canvas>
</div>
<div class="command">
<ul>
<li><a @click="onClickPrev">prev</a></li>
<li><a @click="onClickNext">next</a></li>
</ul>
<ul>
<li><a @click="onClickInput">クイック入力</a></li>
<li><a href="/eating">詳細</a></li>
</ul>
</div>
</div>
<eating-input-dialog-component :show="showInputDialogContent" :datehold=true @update="invokeUpdateList"></eating-input-dialog-component>
</div>
</template>
ダッシュボードからのクイック入力からは、日付の入力はできないようにします。(本日固定にする。)
そのために、コンポーネントにdateholdというパラメータを追加で渡しています。
EatingInputDialogComponent.vue
<template>
<div>
<div id="overlay" v-show="show">
<div id="content">
<p v-if="error_flg == true" class="error">
<ui>
<li v-for="error in errors">{{ error }}</li>
</ui>
</p>
<table class="edit">
<tbody>
<tr>
<td>日付</td>
<td>
<input type="date" v-model="contents.date" v-if="datehold" readonly>
<input type="date" v-model="contents.date" v-else>
</td>
</tr>
<tr>
<td>品名</td>
<td><input type="text" v-model="contents.item" /></td>
</tr>
<tr>
<td>時間帯</td>
<td>
<select name="timezone" v-model="contents.timezone">
<option value="1" selected>朝</option>
<option value="2">昼</option>
<option value="3">夜</option>
<option value="4">間食</option>
</select>
</td>
</tr>
<tr>
<td>タンパク質</td>
<td><input type="number" v-model="contents.protein" /></td>
</tr>
<tr>
<td>脂質</td>
<td><input type="number" v-model="contents.riqid" /></td>
</tr>
<tr>
<td>炭水化物</td>
<td><input type="number" v-model="contents.carbo" /></td>
</tr>
<tr>
<td>カロリー</td>
<td><input type="number" v-model="contents.calorie" /></td>
</tr>
</tbody>
</table>
<p id="command">
<button @click="clickAdd">入力</button>
<button @click="closeModal">閉じる</button>
</p>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['show', 'datehold'],
data() {
return {
errors: [],
error_flg: [],
param: {},
contents: {
date: "",
item: "",
timezone: 1,
protein: "",
riqid: "",
carbo: "",
calorie: "",
},
};
},
created: function() {
this.clear();
},
methods: {
clickAdd: function() {
var self = this;
this.param.contents = this.contents;
axios.post('api/eating/add', this.param).then(function(response){
self.clear();
self.closeModal();
self.$emit('update');
}).catch(function(error){
self.error_flg = true;
self.errors = error.response.data.errors;
});
},
closeModal: function() {
this.$parent.showInputDialogContent = false;
},
clear: function() {
var today = new Date();
this.contents.date = today.getFullYear() + "-" + ('00'+(today.getMonth() + 1)).slice( -2 ) + "-" + today.getDate();
this.contents.item = "";
this.contents.timezone = 1;
this.contents.protein = "";
this.contents.riqid = "";
this.contents.carbo = "";
this.contents.calorie = "";
this.error_flg = false;
this.errors = [];
}
}
}
</script>
ちょっと苦労したのはdateのフォーマットですね。
dateフォームのフォーマットは”YYYY-MM-DD”で、これが若干違っていてもフォームは正しく認識してくれません。
実行結果。