質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.77%

Laravel Validateを使用したCRUDでの、UPDATE時のチェックボックスの値を保持する方法

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,463

YO14

score 41

実現したいこと

(事前)Controllerで use App\Http\Requests\Article\ArticleRequest;
(事前)ArticleRequestに、public function rulesで、name|required のバリデーションルール設定

既存のデータ(例えば名前=鈴木、年齢=45、趣味=チェックボックス群の中から、カメラを選択)をUPDATEするための各項目編集画面を表示する

・名前を空欄にする
・趣味のチェックボックス群において、カメラのチェックを外し、温泉旅行にチェックを入れる

入力内容確認ボタンを押下(正常な動作なら、入力内容確認画面に遷移)

名前が空欄なので、バリデーションエラーメッセージが表示された編集画面が表示される

その際、趣味のチェックボックス群では、温泉旅行にチェックが入っている状態にしたい(元々のカメラのチェックは外れた状態にしたい)

現状

既存のデータ(例えば名前=鈴木、年齢=45、趣味=チェックボックス群の中から、カメラを選択)をUPDATEするための各項目編集画面を表示する

・名前を空欄にする
・趣味のチェックボックス群において、カメラのチェックを外し、温泉旅行にチェックを入れる

入力内容確認ボタンを押下(正常な動作なら、入力内容確認画面に遷移)

名前が空欄なので、バリデーションエラーメッセージが表示された編集画面が表示される

その際、趣味のチェックボックス群では、カメラにチェックが入っている。温泉旅行のチェックは外れている

ソースコード(edit.blade.php)

<div class="form-group @if(!empty($errors->first('media1'))) has->error @endif">
    <label>
        <input type="hidden" name="media1" value=""> <!--チェックボックスが非選択だった時、valueを空で送るための記述 -->
        @if(empty($errors->first('media1'))) <!-- チェックボックスに関するエラーがない場合-->
        <input type="checkbox" name="media1" value="{{$info['media1']}}" @if($info['media1']== "WEB") checked @endif>WEB <!--DBの値がvalueに入る。更にその内容次第で、チェックボックスを選択済みに -->
        @else <!-- エラーが発生したとき-->
        <input type="checkbox" name="media1" value="{{Request::old('media1')}}" @if(Request::old('media1') == "WEB") checked @endif> <!-- エラー直前にこのチェックボックスが選択されていたら、選択済みを保持-->
        @endif
    </label>
    <span class="help-block">{{$errors->first('media1')}}</span>
</div>
<div class="form-group @if(!empty($errors->first('media2'))) has->error @endif">
    <label>
        <input type="hidden" name="media2" value=""> <!--チェックボックスが非選択だった時、valueを空で送るための記述-->
        @if(empty($errors->first('media2')))
        <input type="checkbox" name="media2" value="{{$info['media2']}}" @if($info['media2']== "TV" ) checked @endif>TV <!--DBの値がvalueに入る。更にその内容次第で、チェックボックスを選択済みに -->
        @else <!-- エラーが発生したとき-->
        <input type="checkbox" name="media2" value="{{Request::old('media2')}}" @if(Request::old('media2') == "TV") checked @endif> <!-- エラー直前にこのチェックボックスが選択されていたら、選択済みを保持-->
        @endif
    </label>
    <span class="help-block">{{$errors->first('media2')}}</span>
</div>

ソースコード(ArticlesController.php)

/**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function send_data($id) //編集画面にデータを送る
    {
        $info = Article::find($id);
        return view('article/edit', ['info' => $info]);
    }

ソースコード(ArticleRequest.php)

/**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required'                     
        ];
    }
}

テーブル定義

CREATE TABLE articles (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL,
email varchar(255) NOT NULL,
age int(11) unsigned,
area varchar(255) NOT NULL,
gender int(2) unsigned,
media1 varchar(255),
media2 varchar(255),
note varchar(255) NOT NULL,
image varchar(255) NOT NULL,
created_at timestamp NOT NULL default
current_timestamp,
updated_at timestamp NOT NULL default
current_timestamp
on update current_timestamp,
primary key(id)) ENGINE=InnoDB CHARSET=utf8;

insert文

$info = array(
            'name' => $request->name,
            'email' => $request->email,
            'age' => $request->age,
            'area' => $request->area,
            'gender' => $request->gender,
            'media1' => $request->media1,
            'media2' => $request->media2,
            'note' => $request->note,
            'image' => $request->image,
        );
        Article::insert($info);

DBの値の表示が優先されているようで、どのように記述すればoldの値がvalueに入れられるか分かりません。
また、上記ソースコードだと、
・名前、年齢を正しく入力
・温泉旅行にもチェック(カメラと温泉旅行両方にチェックが付いた状態)
して編集実行しても、温泉旅行がnullになってしまいます。

Laravelにお詳しい方、お知恵をお貸しいただけると有難く存じます。よろしくお願いいたします。

(5/15追記)
以下のように書き換えることで、
・エラーが無く、テーブルの値を参照した際、値が"WEB"であった場合には、チェックボックスはchecked
または
・他の項目でエラーが発生した際、チェックボックスにチェックを入れていた場合(=直前の値が"WEB"であった場合)、チェックボックスはchecked
とすることができました。

ソースコード(edit.blade.php)

<label>
        <input type="checkbox" name="media1" value="WEB" {{(!$errors->has('*') && $info['media1']== "WEB") || old('media1') == "WEB" ? 'checked' : ''}} >WEB <!--DBの値がvalueに入る。更にその内容次第で、チェックボックスを選択済みに -->
    </label>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • YO14

    2019/05/09 12:48

    CREATE文は、以下です。
    CREATE TABLE articles (
    id int(10) unsigned NOT NULL AUTO_INCREMENT,
    name varchar(255) NOT NULL,
    email varchar(255) NOT NULL,
    age int(11) unsigned,
    area varchar(255) NOT NULL,
    gender int(2) unsigned,
    media1 varchar(255),
    media2 varchar(255),
    note varchar(255) NOT NULL,
    image varchar(255) NOT NULL,
    created_at timestamp NOT NULL default
    current_timestamp,
    updated_at timestamp NOT NULL default
    current_timestamp
    on update current_timestamp,
    primary key(id)) ENGINE=InnoDB CHARSET=utf8;

    INSERT文は、Laravelの::insert($~~~);によって実行されていますが、
    以下が詳細です。$dataが、$infoであるとお考えください。
    $data = array(
    'name' => $request->name,
    'email' => $request->email,
    'age' => $request->age,
    'area' => $request->area,
    'gender' => $request->gender,
    'media1' => $request->media1,
    'media2' => $request->media2,
    'note' => $request->note,
    'image' => $request->image,
    );
    Article::insert($data);

    キャンセル

  • m.ts10806

    2019/05/09 12:54

    質問本文に追記願います。
    コメント欄ではマークダウンが使えませんし、デフォルトは非表示ですので

    キャンセル

  • YO14

    2019/05/09 13:00

    追記いたしました。
    $infoには、DBからidで紐づけて取得した各種データが格納されています。(名前、性別等…)

    キャンセル

回答 2

checkベストアンサー

+1

そもそも、チェックボックスの使い方の認識?が間違っているのかな、と思いました。

チェックボックスのvalue、ラジオボタンのvalue、プルダウンのoptionのvalue、
これらは「システム側で決められた値」であることが通常です。

つまり、テキストボックスと違い、valueそのものに登録or入力されたデータ値を参照する必要はなく、「選択済みにするかしないか」の点で、登録or入力されたデータ値を参照します。

また、選択済みにするかしないかの参照先判定(登録データをみるか、入力値を見るか)は、
「エラーがなければ、登録データをみて」あるいは「入力値をみて」くらいでいいのかなと思われます。

それから、$errosはインスタンス自体はいつでも存在する為、エラーの全体の有無をempty($errors)では正しく判定できないので、!$errors->has('*')で、「何もエラーを持っていない」と判定します。

これら3点を踏まえて、簡単にまとめるとこんな感じになります。

例:WEBのチェックボックス

<input type="checkbox" name="media1" value="WEB" {{(!$errors->has('*') && $info['media1']== "WEB") || (old('media1') ?? '')== "WEB" ? 'checked':'' }} >WEB

※登録フローに「確認画面」が存在し、確認画面から入力画面へ戻れる仕様の場合、もう少し工夫が必要だと思うので、あくまでご参考までに。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/12 22:36

    ご回答ありがとうございます。
    いただいたコードの条件分岐の箇所ですが、
    (old('media1') ?? '')== "WEB" の箇所が、どういう処理をしているのか分かりません、教えていただけませんでしょうか。

    ①エラーが発生しておらず、かつ前のページからPOSTされた$info['media1']の中身が"WEB"である
    または
    ②エラー発生直前に入力された値であるold('media1')が??NULLではなく??かつ、"WEB"のとき、'checked'が表示される

    キャンセル

  • 2019/05/13 15:26 編集

    ?? は、isset判定の簡易記述みたいなやつです。。。見慣れた感じに書きかえると、
    if (isset(old('media1'))) { old('media1') } else { '' } こんな感じのことしてます。
    入力欄の初期値とかに使うと便利なのですが、これはなくても問題有りません。(つい癖で書いてしまった。。)
    「 ?? ’’ 」の部分が、あってもなくても

    ①エラーが発生しておらず、登録データ($info)のmedia1の中身が"WEB"である
    または、
    ②直前に入力された値が、"WEB"である
    のいずれかで、’checked’

    ってことになるので、回答に書いた判定内容以上のことはしていないです。

    キャンセル

  • 2019/05/15 18:10

    <label>
    <input type="checkbox" name="media1" value="WEB" {{(!$errors->has('*') && $info['media1']== "WEB") || old('media1') == "WEB" ? 'checked' : ''}} >WEB
    </label>

    とすることで、初期値がWEBである場合、またはエラー直前の値がWEBであった場合、checkedとすることができました。
    ありがとうございます。

    キャンセル

+1

<input type="checkbox" name="media[]" value="1" @if(is_array(old('media')) && in_array(1, old('media'))) checked @endif> WEB
<input type="checkbox" name="media[]" value="2" @if(is_array(old('media')) && in_array(2, old('media'))) checked @endif> TV
<input type="checkbox" name="media[]" value="3" @if(is_array(old('media')) && in_array(3, old('media'))) checked @endif> GAME
<input type="checkbox" name="media1" value="1" @if(null !== old('media1')) checked @endif> WEB
<input type="checkbox" name="media2" value="2" @if(null !== old('media2')) checked @endif> TV
<input type="checkbox" name="media3" value="3" @if(null !== old('media1')) checked @endif> GAME


気になったので調べて見ましたけど、結構記事落ちてましたよ。

今回のアンサーの方法
https://stackoverflow.com/questions/39521726/how-to-show-old-data-of-checkbox-in-laravel

ヘルパーを作る方法
https://qiita.com/namizatop/items/fab4f78438d3d1940acd

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/12 23:40

    ご回答ありがとうございます。ググり力不足で申し訳ございません。
    ご提示いただいた記事を拝見しましたが、stackoverflowの方は、チェックボックスの値を配列形式にしているのか、私のやり方と違ったためそちらの疑問が湧いてしまい、上手く落とし込めていません。

    また、2番目に記述いただいている3行のコードですが、
    「もしold('media1')がNULLでなかったら、checkedにする」という理解で宜しいでしょうか。
    その場合ですと、その判定の前に
    「エラーが発生しているか、していないか」
    「POSTされてきた値が存在するか、しないか」
    を書かなくてはいけないと思っているのですが、上手く書けずにいます。if文の中にif文を書くのが苦手でして…。
    「こう書けばいいのでは?」といったアドバイスをいただけると有難く存じます。

    キャンセル

  • 2019/05/14 02:07 編集

    始めに私はバージョン5.5を扱っています。ご考慮ください。
    old('media') は直前の入力値を参照します。mediaのvalueの値がNULLであるかないかを判定しています。

    処理順に関しては問題ないと思います。何故checkboxのvalueをoldヘルパーやデータベースから取得しているかという点は疑問です。

    mediaの名前が変わるなら、$info['media1']== "WEB"がエラーの原因となります。判定条件を存在の有無にしたほうがいいと思います。その場合はvalueの値は何でも大丈夫です。
    mediaの名前が変わらないなら、valueの値はどう転んでも同じです。media1なら'WEB'と固定してしまうのもいいでしょう。
    重要なのはcheckedを付けるか付けないかです。

    $errorが常に存在していることをもうお一方の回答ではじめて知りました笑
    まずはemptyメソッド消すところをやってみてはいかがでしょうか?

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る