アプリ版:「スタンプのみでお礼する」機能のリリースについて

今まで、PHP5+MySQL5で、ラジオボタンをつかったPHPフォームを少し作った経験がありますが、チェックボックスを使った経験がなく、PHPフォームやMySQLのDB構成の基本的なところの考え方でつまづきました。


以下の好きな球技のアンケートをとると仮定した具体例で、考え方などアドバイスいただけると幸いです。


(1) HTML側は、こういうチェックボックス
[ ]野球
[ ]蹴球
[ ]庭球

(2) MySQL側は、こういうテーブルが作ってあり、チェックが入っていたら「1」をINSERT。
`kyugi1` char(1) default NULL COMMENT '好きな球技(野球)',
`kyugi2` char(1) default NULL COMMENT '好きな球技(蹴球)',
`kyugi3` char(1) default NULL COMMENT '好きな球技(庭球)',


(3) で、あとでこのアンケート結果を集計リストアップするための別ページを作る際に、こういう検索フォームを設け、
<form>
<input type="checkbox" value="0" name="kyugi[]"<?php if ($_GET["kyugi"] == 0) { echo " checked";} ?>野球
<input type="checkbox" value="1" name="kyugi[]"<?php if ($_GET["kyugi"] == 1) { echo " checked";} ?>蹴球
<input type="checkbox" value="2" name="kyugi[]"<?php if ($_GET["kyugi"] == 2) { echo " checked";} ?>庭球
</form>

(4) その際、SQL文を作ろうとしたら、「あれ?」となりました。
if(is_array($_GET["sports"])){
$sql = " select * from mytable where sports in ('" . implode("','", $_GET["sports"]) . "')";
}


【質問1】「ラジオボタンのように択一した(1つを選ぶ)」レコードなら、(3) (4) のような抽出方法で今までうまくやってきましたが、
「チェックボックスのように複数選択された」レコードだと、MySQL側には、全ての選択肢(ここでは野球、蹴球、庭球の3つ)について
フィールドを儲けなければならないですよね?例えば、kyugi1、kyugi2、kyugi3とか、baseball、football、tennisで、チェック入っていたら1、入っていなければ0を
Insertするとか。
「kyugi」というフィールドに、選択された複数のvalue(012、02、12、などと)を格納する、なんてやり方はしませんよね?


【質問2】チェックボックスの選択肢は、今はまだ野球、蹴球、庭球の3つだけですが、いずれ配球、篭球。。。と増加する可能性があります。
この場合、以下のようなマスターを設けて切り出した方がメンテナンス性良いでしょうか?この程度ならそこまで拡張しなくていいでしょうか?
kyugiID/kyuginame
0/野球
1/蹴球
2/庭球


【質問3】(3)の検索フォームですが、
野球だけチェックして検索したら、野球だけchekedを残したいから
<?php if ($_GET["kyugi"] == 0) { echo " checked";}
というのを仕込んでありますが、

はじめに当該フォームのHTMLページに飛んできたときは、既定値としてmすべてのチェックボックスにチェックを入れておきたいのですが、妙案ないでしょうか。。。

よろしくお願い致します。

質問者からの補足コメント

  • すみません、本当にそのまま使えるGETの受け渡しをいただいて感謝感謝なのですが、ベストアンサーが1つしか選べないようで、今回すみません。

    No.1の回答に寄せられた補足コメントです。 補足日時:2021/10/19 18:45

A 回答 (3件)

1.


複数の列(column)をレコードに持たせる設計は悪手です。
複数個の値を扱うならば、
複数レコードに分けるか、JSON 型の配列として持たせましょう。

参考) 最近の MySQL なら JSON 型の配列でも効率よく検索できます
https://dev.mysql.com/doc/refman/8.0/ja/create-i …

2.
マスターを持たせたほうが都合がよいでしょう。
<form> 内もマスターを使った foreach で簡略化できます。

例)
$sports_master = array( ["val"=>1, "name"=>"野球"], ... );
...
<?php foreach ($sports_master as $m) { ?>
<label>
<input name="c[]" value="<?= $m['val'] ?>">
<?= $m['name'] ?>
</label>
<?php } ?>

3.
検索ボタンを押したか判別する GET/POST 引数を用意して、
引数が無ければ全有効としてはいかがでしょう

例)
<button type=submit name=z>送信</button>
...
if (!isset($_GET['z'])) { // 引数に z が無い → ボタン押してない
_ $checked = true;
} else {
_ $checked = 引数からチェック有無を判定する処理();
}
    • good
    • 0
この回答へのお礼

Ogre7077さん、わかりにくい説明に1問ずつご回答ありがとうございます。

> 複数の列(column)をレコードに持たせる設計は悪手です。
> 複数個の値を扱うならば、複数レコードに分けるか、


やはり悪手なんですね。しかし、好き・嫌いを1と0で表すと、
球技の数だけ列(column)をレコードに持たさざるをえない発想から抜け出せません、

    野球 蹴球 庭球
回答者1  1  0  1
回答者2  1  0  0
回答者3  1  1  1
回答者4  1  1  0
回答者5  0  0  1
 :
 :

あと、URLお示しいただいた「JSON 配列のインデックス付け」は環境がMySQL5なのと、ちょっと私には高度過ぎるかもしれません、、、(せっかくなのにすみません)

2は目からうろこ、具体的コードご提示もありがとうございます。是非マスター化してみます。
3も引数が無ければ全有効、というお示しのコードでよくイメージ
できました、適用させていただきます!!

お礼日時:2021/10/19 00:31

No.2 の補足


> 球技の数だけ列(column)をレコードに

次善の案として、
一つの列に、有効無効の桁を複数並べた文字列は如何でしょうか。
like 句を使ったパターンマッチ検索なので、
他案に比べて速度的には不利になりますのでご了承ください。

insert into 表(sports) values ('101'); -- 野球と庭球は有効
insert into 表(sports) values ('011'); -- 蹴球と庭球は有効

select * from 表 where sports like '1__'; -- 野球が有効
select * from 表 where sports like '_11'; -- 蹴球と庭球の両方が有効

参考)
https://dev.mysql.com/doc/refman/5.6/ja/pattern- …
    • good
    • 0
この回答へのお礼

Ogre7077さん、度々ありがとうございます。
そんなシビアなWebシステムではないので、速度は構わないのですが
仰せのような発想はなかったです!
ご提示いただいた方法含めてシンプルかつメンテ性が高そうな方策を検討してみます。

お礼日時:2021/10/19 18:42

テーブル構成はもうすこしねったほうがよいでしょう。


getの受け渡しはこんな感じ
<?PHP
$kyugi=filter_input(INPUT_GET,"kyugi",FILTER_VALIDATE_INT,FILTER_REQUIRE_ARRAY);
$checked["kyugi"]=[0=>"",1=>"",2=>""];
if($kyugi){
foreach($kyugi as $val){
$checked["kyugi"][$val]=" checked";
}
}
?>
<form>
<label><input type="checkbox" value="0" name="kyugi[]"<?=$checked["kyugi"][0]?>>野球</label>
<label><input type="checkbox" value="1" name="kyugi[]"<?=$checked["kyugi"][1]?>>蹴球</label>
<label><input type="checkbox" value="2" name="kyugi[]"<?=$checked["kyugi"][2]?>>庭球</label><br>
<input type="submit" value="send">
</form>
この回答への補足あり
    • good
    • 0
この回答へのお礼

yamabejpさんご無沙汰しております、具体的なコードでお示しいただきありがとうございます。いつも本番環境にそのまま適用できる実用的なサンプルをいただき、いくつも今でも使わせていただいております。
filter_inputの一行はチンプンカンプンなワザを一つずつ解読してみますね。

お礼日時:2021/10/19 00:25

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

関連するカテゴリからQ&Aを探す


このQ&Aを見た人がよく見るQ&A