@yasu_2244

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

性別を選択してもらった後、確認画面で文字で表示させ データベースへ数値として送信したい

解決したいこと

ラジオボタンで性別を選択してもらった後、確認画面で男性、または女性を文字で表示させ
データベースへ数値として送信したいです。

発生している問題・エラー

inputタグの後にlabelタグを追加して色々試しましたが
Undefined index

SQLSTATE[HY000]: General error: 1364 Field 'gender' doesn't have a default value (SQL: insert into `contacts(...)

等のエラーがでてしまっています。

該当するソースコード

フォーム画面

 <div class="contact-form__content">
    <div class="contact-form__heading">
      <h2>お問い合わせ</h2>
    </div>
    <form class="form" action="contacts/confirm" method="post">
        <div class="form__group">
        <div class="form__group-title">
          <span class="form__label--item">性別</span>
          <span class="form__label--required">※</span>
        </div>
        <div class="form__group-content">
          <div class="form__input--radio">
              <input id="men" type="radio" name="gender" value="1" checked>
              <label for="men" name="gender2" value="男性">男性</label>
              <input id="women" type="radio" name="gender" value="2">
              <label for="women" name="gender2" value="女性">女性</label>
          </div>
        </div>
      </div>
    </form>
 </div>

確認画面

<tr class="confirm-table__row">
  <th class="confirm-table__header">性別</th>
  <td class="confirm-table__text">
    <input type="text" name="gender" value="{{ $contact['gender2'] }}" readonly />
  </td>
</tr>

マイグレーションファイル

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateContactsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('contacts', function (Blueprint $table) {
             $table->string('fullname');
             $table->tinyInteger('gender')->comment('性別:1=男性、2=女性');
             $table->string('email');
             $table->char('postcode');
             $table->string('address');
             $table->string('building_name')->nullable();
             $table->text('opinion', 120);
             $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('contacts');
    }
}


コントローラー

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Contact;

class ContactController extends Controller
{
    public function index()
    {
        return view('index');
    }
    public function confirm(Request $request)
    {   
        $contact = $request->only(['last_name', 'first_name', 'gender2', 'email', 'postcode', 'address', 'building_name', 'opinion']);

        return view('confirm', ['contact' => $contact]);
    }
    public function store(Request $request)
    {
        $contact =  (['fullname' => $request->last_name . $request->first_name] + $request->only(['gender', 'email', 'postcode', 'address', 'building_name', 'opinion']));
    
        Contact::create($contact);

        return view('thanks');
    }
}

自分で試したこと・考えていること

上記のソースコードでは一部省略しております。足りなり部分があれば指摘お願い致します。
このコードでは確認画面の段階でUndefined indexエラーがでます。
まず自分がやろうとしていることは、valueで初期値を設定して確認画面で表示させるために
controllerでcontact変数を定義してconfirmで呼び出す。
(この時に文字で表示させたいのでlabelタグに別のnameと初期値を定義してはどうかと思ったのでこういった記述になりました。)
その後、store関数の方でデータべースへtinuint型でデータを送りたいのでinputタグのnameを使用して$contactに入れています。
問題はinputタグやlavelタグの属性の使い方かと思いますが、浅学のため解決法を調べてもわかりませんでした。
ご教授お願い致します。

【追記・解決方法】
アドバイスのおかげで解決できました。
<label>タグからgender2を消して、controllerのgender2genderに変更。
そして、確認ページで条件分岐させればできました。
formタグでデータ数字で送信するのでinputタグのtype属性はhiddenに変更しました。

確認画面

  <input type="hidden" name="gender" value="{{ $contact['gender'] }}" readonly />
      <?php
      if ($contact['gender'] == '1') {
          echo '男性';
        } else if ($contact['gender'] == '2') {
          echo '女性';
        }
      ?>
0 likes

3Answer

Undefined index

どのような値が送られてきているのか確認してみましょう。

$request->all()

SQLSTATE[HY000]: General error: 1364 Field 'gender' doesn't have a default value (SQL: insert into `contacts(...)

INSERTにおいて「フィールド xxx はデフォルト値を持たない」というエラーは、デフォルト値が設定されていないフィールドに対して値の指定がない、ということです。

テーブルのフィールドと挿入しようとしている値(変数$contactの中身)を確認してみましょう。

ラジオボタンで性別を選択してもらった後、確認画面で男性、または女性を文字で表示

まず<label>タグはラベル付けの要素なので、フォーム要素のように値を送信するものではないです。

これを実現する方法ですが、性別の値(1,2)は送られてくるわけですからそこからラベルを判別することができます。数値とラベルのマッピングはシステムで決めているわけですから、これが可能です。

ラベルの値も送信することはJavaScriptを使えば可能です。ただ、数値の値と常に同期していないといけないのと、数値の値から判断できるので冗長です。なので最初の方法をお勧めします。

1Like

Comments

  1. @yasu_2244

    Questioner

    丁寧にありがとうございます。
    <label>タグにはそのような機能はないのですね、勉強になりました。
    最初の方法とは、

    これを実現する方法ですが、性別の値(1,2)は送られてくるわけですからそこからラベルを判別することができます。

    だと思うのですが、
    そこからラベルを判別というのが理解できませんでした。
    まず<label>タグの初期値などは削除して
    フォームで選択してもらった後にコントローラーでHTTPリクエストを行い
    入力データを取得した後に数値を文字に変えるのかと思ったのですが…。

    浅学のためお手数をおかけしますが、もう少し考え方をご教授願います。

  2. 承知しました。ではもう少し具体的に説明してみますが、そんな複雑な話ではなくてですね、
    「1=男性、2=女性」というのは決まっているわけですから、1か2か選択されれば条件分岐などで男性か女性か判断が可能、という考えです。

    if ($gender == '1') {
        echo '男性';
    } else if ($gender == '2') {
        echo '女性';
    }
    

    なので日本語表記をフォームから送る必要はなく、数値を日本語表記に変換して確認画面で見せます。

  3. @yasu_2244

    Questioner

    本当にご丁寧にありがとうございます!
    なるほど、条件分岐まったく考えつきませんでした…。
    おかげさまで、無事解決できました。
    ありがとうございました。

ざっと見た感じでは、テーブルの性別のカラムはgenderとなっているのに、登録処理がgender2として登録しようとしているので、genderの情報としてSQLに認識されていないようにお見受けが、いかがですか?

あと、すごくメンドウごとと思われるかもしれませんが、昨今の状況を踏まえると、ジェンダーには3番「未回答」を追加した方が無難であると感じます。関係ないことですみません。

0Like

Comments

  1. @yasu_2244

    Questioner

    ご指摘ありがとうございます、色々試していたので誤記したままでした!
    訂正しておきます。

    「未回答」の追加もおっしゃる通りです。
    まだ勉強の身ですが、常にそういった意識を持つことは大事ですよね。
    解決したら追加してみようと思います!

  2. うお、ということはgenderに直してもダメだったということですかね?
    そのときもdefault valueのエラーですか?

  3. @yasu_2244

    Questioner

    <label>タグには値を送信できないとのご指摘をしてもらったので
    gender2自体を削除しました!
    結論を言うと、エラーは消えてます。
    この状態ではデータ送信は出来ています。
    ただ、初期値が数値なので確認画面では「男性」の表記ではなく
    「1」となっています。
    データベースには数値で送信したいのですが、確認画面では数値ではなく
    「男性」または「女性」と表記したいと思っております。

    【追記】
    解決しました、ありがとうございました!

laravel の話なら laravel のタグをつけてください。

エラーメッセージは「DB に insert する際に gender に値が渡されてないのでデフォルト値を使おうとしたが、DB の当該フィールドにデフォルト値が設定されてない」と言ってるように見えますが、心当たりはないですか?

エラーメッセージでググってみるとかしましたか?

0Like

Comments

  1. @yasu_2244

    Questioner

    申し訳ございません、追加しました。

    本文の方も説明不足で申し訳ないです。
    マイグレーションファイルにgenderと登録してあるので
    mysqlの登録する処理の所でgenderで渡さないといけないと理解しています。
    そして、labelタグなしでinputタグに初期値(1,2)を入れるだけなら登録ができています。
    ご指摘のエラーはlabelタグにも値を送信させようとしたところ、起こったエラーなので
    載せるべきではなかったか、エラーがどう起こったのか別途説明をすべきでした。
    わかりにくくしてしまい申し訳なかったです!

  2. ご指摘のエラーはlabelタグにも値を送信させようとしたところ

    意味が分かりません。「labelタグ」というのは「フォーム画面」の label タグのことですよね? label タグでは値をサーバーに送信するなんてことは不可能ですけど。 

    そもそも、どういう順序でどこに何を送信したいのでしょうか?


    【追記】

    Laravel とか触ったこともないのでハズレかもしれませんが・・・

    質問に書いてある「フォーム画面」のコード、

    <form class="form" action="contacts/confirm" method="post">
      <input id="men" type="radio" name="gender" value="1" checked>
      <label for="men" name="gender2" value="男性">男性</label>
      <input id="women" type="radio" name="gender" value="2">
      <label for="women" name="gender2" value="女性">女性</label>
    </form>
    

    で form を送信すると、例えばユーザーが男性を選んだとするとコンテンツには gender=1 が含まれてサーバーに送信されます。

    それをコントローラーの以下の confirm メソッドで受けるのだろうと思いますが、$request には gender=1 が受け取れたとしても、

    public function confirm(Request $request)
    {   
        $contact = $request->only(['last_name', 'first_name', 'gender2', 'email', 'postcode', 'address', 'building_name', 'opinion']);
    
        return view('confirm', ['contact' => $contact]);
    }
    

    その下の $contact = $request->only([... 'gender2', ...]); では名前が gender2 と違うのでダメということではなかろうかと思いますけど、違いますか?

  3. @yasu_2244

    Questioner

    ご指摘のとおりです、ありがとうございます。
    調べてわからなかったのでこういった手段を試した次第です。
    まだまだhtml自体が勉強不足でした。

    フォームで性別を選択してもらった後、確認画面では「男性」、「女性」と表記し
    データベースに性別の値を数値(1or2)として送信したいと思っております。

    追記の方確認させてもらいました。
    おっしゃる通りだと思います。
    HTTPリクエストの理解度が浅かったと思います。
    受け取っていないgender2を渡されてエラーが出ていたという事と理解しました。
    ありがとうございます。

  4. フォームで性別を選択してもらった後、確認画面では「男性」、「女性」と表記しデータベースに性別の値を数値(1or2)として送信したいと思っております。

    普通に Web アプリなら、ブラウザから 1 が送信されてきたら「男性」と、2 なら「女性」と表示するなんてことは何の問題も苦労もなく可能です。サーバー側のアプリのコードで変換すればいいわけですから。

    Laravel だってできると思いますよ。よく調べてみてください。

  5. @yasu_2244

    Questioner

    条件分岐で出来ました!
    お付き合いくださり、ありがとうございました。

Your answer might help someone💌