laravelで入力値の引き継ぎ機能を作ろうとしたらつまづきまくったので全部メモ

#これがしたい
入力値の引き継ぎ
登録したあと消えないでほしい。登録後変更もできるようにしたい。

#やったこと
1.[クラスprofileのインスタンスを作成](#クラスprofileのインスタンスを作成)
2.[テキストエリアとセレクトボックス入力値の引き継ぎ](#テキストエリアとセレクトボックス入力値の引き継ぎ)
3.[インスタンス名->seve()の有り無し](#インスタンス名->seve()の有り無し)
4.[複数チェックボタン](#複数チェックボタン)
5.[データーベースで扱う値は'code'ではなく'id'にしたほうがいい](#データーベースで扱う値は'code'ではなく'id'にしたほうがいい)
6.[初期値の空判定](#初期値の空判定)

#1.クラスprofileのインスタンスを作成
profileコントローラーのupdate()で

```php
$profile = Profile::where('user_id', $user['id'])->first();
if (empty($profile)) {
            $profile = new Profile();
        }
```
ユーザーIDを元に該当のレコードを取得する。
もしユーザーIDがなかったらインスタンス作成する。

※ここのif文を書いてなかったから更新したいのに、無限に登録され続けた。


#2.テキストエリアとセレクトボックス入力値の引き継ぎ

profileコントローラーで定義

```php
public function update(Request $request)
    {
      $inputs = $request->all();
      $profile->academic_background = $inputs['academic_background']; // 学歴（詳細）
    }
```
profileブレードで定義

```php
<div class="form-group">
    <?php $inputName = 'academic_background'; ?>
    {!! Form::label($inputName, '学歴（詳細）', ['class' => 'col-form-label']) !!}
    <div class="col-sm-10">
    {!! Form::textarea($inputName, $profile->$inputName, ['rows' => '4','cols' => '1', 'class' => 'form-control']!!}
     </div>
 </div>
```

これでテキストエリアとセレクトボックスの入力値は引き継ぐことができた。

#3.インスタンス名->seve()の有り無し
profileコントローラーのupdate()をする際に気をつけることがもう一つある。

```php
$profile->save();
```
有りだと更新。無しだと登録。
気をつけよ。

#4.複数チェックボックス
他のフォーム情報は1：1だったから、同じテーブルに渡せたが、複数チェックボックスだと1：多のテーブルを作らなければいけない。中間テーブルってやつ。その記事↓
https://qiita.com/kusano00/items/001bdc353136935bf4f4
(イメージ)
プロフィールID　1　

特技

- [x] 野球(ID1)
- [ ] ラグビー(ID2)
- [x] サッカー(ID3)


↓こうなってればいい

|  プロフィールID | 特技ID |
| --- | --- |
|  1 | 1 |
|  1 | 3 |

###作っていく

特技(skills)テーブル作る

```php
    public function up()
    {
        Schema::create('skill_profiles', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('profile_id')->unssigned()->index('profile_id')->comment('プロフィールID');
            $table->integer('skill_id')->unsigned()->index('skill_id')->comment('特技ID');
            $table->timestamps();
        });
    }
```

profileモデルに追記

```php
public function skills()
    {
        return $this->belongsToMany('App\Models\Skill', 'skill_profiles', 'profile_id', 'skill_id')->orderBy('sort')->withTimestamps();
    }
```

第1引数　値を取得したいクラス
第2引数　テーブル名
第3引数　外部キー
第4引数　関連キー

profileコントローラーのupdate()に追記

```php
$profile->skills()->detach();
        $dates = $inputs['skill'];
        foreach ($dates as $date) {
            $default = Jobtype::where('code', $date)->first();
            $profile->skills()->attach($default['id']); // 特技
        }
```

detach()で前回のフォーム情報を削除
※detach()しないと前回情報も追加されるので注意
'code'を'id'に変換してprofileテーブルに格納。

更にinput()に追記

```php
$skills = $profile->skills()->pluck('code')->toArray();
return view('user.profile.input')
   ->with('skills', $skills)
```

profileインスタンスの→skills()でID絞って→IDに該当する'code'取得->配列で
※デフォルト値セットする際にin_arrayでtrueにするため、配列。
viewに変数渡す。

profileブレードに追記

```php
 <div class="form-group">
  <?php $inputName = 'skill'; ?>
  {!! Form::label($inputName, '特技', ['class' => 'col-form-label']) !!}
 　<div class="col-sm-10">
    @foreach($selectSkills as　$selectSkillCode => $selectSkillValue)
       <div class="form-check form-check-inline">
       {!! Form::checkbox($inputName.'[]', $selectBusinesstypeCode, in_array($selectSkillCode,$skills)  , [ 'id' => $inputName .$selectSkillCode, 'class' => 'form-check-input']) !!}
       {!! Form::label($inputName . $selectSkillCode, $selectSkillValue, ['class' => 'form-check-label']) !!}
       </div>
    @endforeach
  </div>
</div>
```

チェックボックスの引数
第1引数　フォーム名
第2引数　value
第3引数　デフォルト値
第4引数　属性

in_arrayの引数
第1引数　文字列
第2引数　整数の配列
（第3引数　true入れた方が良いが今回はうまく動作しなかったのでパス）

#5.データーベースで扱う値は'code'ではなく'id'にしたほうがいい
理由：'code'は値を変更したい時があるが、'id'は変更しない。

前提：$profile->preferred_workplaceの値は'code'

変更方法：profileコントローラーのupdete()で

```php
$inputs = $request->all();
```
フォームの入力値を取得して
profileインスタンスの'preferred_workplace'に格納。

```php
$profile->preferred_workplace = $inputs['preferred_workplace']; // 希望勤務地
```
これだとフォーム入力値（'code'）がそのまま入ってしまうのでちょっと改良。

```php
$date = $inputs['preferred_workplace'];
$default = Prefecture::where('code', $date)->first();
$profile->preferred_workplace = $default['id']; // 希望勤務地
```

|  $date | フォーム入力値の 'code' 取得 |
| --- | :--- |
|  $default | Prefectureクラスのカラム名codeが$date(フォーム入力値)のレコードを一つだけ取得 |
|  $profile | 取得したレコードのカラム名idをprofileテーブルに格納 |

データベースに渡す値を'id'に変換できたが、入力値の引き継ぎするときの値は'code'じゃないといけないからprofileコントローラーのinput()で'code'取得して->withしてあげる

```php
public function input()
{
 $preferred_workplace=Prefecture::where('id',$profile['preferred_workplace'])->first();

return view('user.profile.input')
->with('preferred_workplace', $preferred_workplace)
}
```

#6.初期値の空判定

profileコントローラーのinput()に追記

```php
 if (empty($profile)) {
            $academic_background = null;
        }else{
            $academic_background = $profile->academic_background;
        }

 return view('user.profile.input')
      ->with('academic_background',$academic_background)
```

空のときはnullを入れて、そうじゃなかったらオブジェクト値を変数に入れる。->withでviewに渡す。

profileブレードを修正

```php
{!! Form::textarea($inputName, $academic_background, ['class' => 'form-control' ]) !!}
```
デフォルト値で$profile->academic_backgroundのように、オブジェクトで取っていたがエラー出ちゃうので、変数に変更

###複数チェックボックスの場合

コントローラー追記

```php
 if (empty($profile)) {
            $preferred_job_types = array();
        } else {
            $preferred_job_types = $profile->preferred_job_types()->pluck('code')->toArray();
        }

return view('user.profile.input')
->with('preferred_job_types', $preferred_job_types)
```

ブレード修正

```php
@foreach($selectJobtypes as $selectJobtypeCode => $selectJobtypeValue)
   {!! Form::checkbox($inputName.'[]', $selectJobtypeCode,in_array($selectJobtypeCode,$preferred_job_types), [ 'id' => $inputName . $selectJobtypeCode, 'class' => 'form-check-input']) !!}
   {!! Form::label($inputName . $selectJobtypeCode, $selectJobtypeValue, ['class' => 'form-check-label']) !!}
@endforeach
```