電子書籍の厳選無料作品が豊富!

プログラム初心者です

質問1
HTMLのフォームのチェックボックスから配列でphpに値を渡したときにチェックした値が1個しかなかった時には配列として受け取っているのでしょうか?それとも一個しかない場合は変数として受けとっているのでしょうか?

現状ではissetで調べて値がある場合にはその配列をforeachで取り出して実行しています(実際にやってみたら値1個でも動いていますが気になったので教えてください)
値のチェックはissetのみでいいでしょうか?



質問2
MySQLの方は、チェックの個数分のレコードを削除するために繰り返し処理の中でsqlを最大20回発行するのはダメな処理ですか?(チェック1個の場合は1回のみsqlを発行しています)
一般的に使われているならこれでいこうと思います



よろしくお願いします

A 回答 (2件)

(インデントには全角スペースを使わせていただきます。

)


【回答1】

1個以上 → 配列です。
0個 → 受け取りません。

手を抜くなら isset だけで十分ですが、厳密に "不正な" リクエストも考慮するならば is_string / is_array を活用した型チェックも欠かせません。毎回全部このチェックを記述するのは面倒なので適当に関数を作っておくといいでしょう。あらゆるニーズに対応できるように作成した関数があるので良ければ活用してください。

汎用的な変数構造フィルタリング関数
http://qiita.com/mpyw/items/c39b9ee695a5c2e74627

構造をフィルタリングすると同時にUTF-8バリデーションが行われ、UTF-8として正しくないバイト列を検知して無効化します。他の言語ではこういったエンコーディングバリデーションをするのがほぼ当たり前になってるようですが、PHPでは何故かあんまり浸透していないみたいですね・・・

使用例:

名前: <input type="text" name="name" value="" /><br />
<input type="checkbox" name="checks[]" value="A" />A<br />
<input type="checkbox" name="checks[]" value="B" />B<br />
<input type="checkbox" name="checks[]" value="C" />C<br />
備考1: <input type="text" name="options[]" value="" /><br />
備考2: <input type="text" name="options[]" value="" /><br />



extract(filter_struct_utf8(INPUT_POST, array(
  'name' =>
    FILTER_STRUCT_FULL_TRIM,
  'checks' =>
    FILTER_STRUCT_FORCE_ARRAY,
  'options' =>
    FILTER_STRUCT_FORCE_ARRAY | FILTER_STRUCT_FULL_TRIM,
)));

これで

$name … 両端がトリミングされた文字列
$checks … 一次元配列
$options … 要素が全てトリミングされた一次元配列

になることが必ず保証されます。

しかし、チェックボックスに関しては、これではフォーム上に存在するものかどうかまでの確認は出来ません。もしそれを行いたいのであれば、そもそも「値」でチェックしようとするのをやめ、「キー」でチェックしてください。具体的には下記のようにします。

名前: <input type="text" name="name" value="" /><br />
<input type="checkbox" name="checks[0]" value="A" />A<br />
<input type="checkbox" name="checks[1]" value="B" />B<br />
<input type="checkbox" name="checks[2]" value="C" />C<br />
備考1: <input type="text" name="options[]" value="" /><br />
備考2: <input type="text" name="options[]" value="" /><br />



$default_checks = array('A', 'B', 'C');
extract(filter_struct_utf8(INPUT_POST, array(
'name' =>
    FILTER_STRUCT_FULL_TRIM,
  'checks' =>
    array_fill(0, count($default_checks), null),
  'options' =>
    FILTER_STRUCT_FORCE_ARRAY | FILTER_STRUCT_FULL_TRIM,
)));

これで $checks の各要素が NULL かどうかの判定を行えばいいだけです。変数が定義済みであることが確定しているので、 isset を使う必要はありません。単純に !== null として比較してください。


【回答2】

1回で全部削除できますよ。PDOのプリペアドステートメントを用いるならば、上記の $checks を受け取った後、

foreach ($checks as $k => $v) {
  if ($v !== null) {
    $params[] = $default_checks[$k];
  }
}
if (!empty($params)) {
  $sql = sprintf(
    'DELETE FROM table WHERE checks IN (%s)',
    implode(', ', array_fill(0, count($params), '?'))
  );
  $stmt = $pdo->prepare($sql);
  $stmt->execute($params);
}

というように、「WHERE ... IN ( ... )」の条件部分に可変長のプレースホルダを設けてください。なお、$v は NULL でないかどうかを判定するためだけに用い、それ以外の用途に使ってはいけません。それが「A」「B」「C」のどれかである保証はないからです。



あと、言うまでもないですがCSRF攻撃対策は行ってくださいね・・・!
    • good
    • 0
この回答へのお礼

回答ありがとうございます
すいません。mysqliの手続き型で同じようなことはできますか?

お礼日時:2013/12/02 19:58

Mysqli手続き型ならこうですかね・・・


(手続き型はコードが長くなるのであんまり好きじゃないですが)

foreach ($checks as $k => $v) {
  if ($v !== null) {
    $params[] = $default_checks[$k];
  }
}
if (!empty($params)) {
  $sql = sprintf(
    'DELETE FROM table WHERE checks IN (%s)',
    implode(', ', array_fill(0, count($params), '?'))
  );
  $stmt = mysqli_prepare($link, $sql);
  call_user_func_array(
    'mysqli_stmt_bind_param',
    array_merge(
      array($stmt),
      array(str_repeat('s', count($params))),
      $params
    )
  );
  mysqli_stmt_execute($stmt);
}

Mysqli使ったこと無い上にデバッグしてないのでミスあったらごめんなさい m(_ _)m
    • good
    • 0
この回答へのお礼

回答ありがとうございます
無理いってすいません。いろいろと参考になりました

お礼日時:2013/12/03 01:38

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