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

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

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

1608閲覧

PHPにおける0、NULL、空の区別。

Take_it

総合スコア357

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2019/06/03 01:11

編集2019/06/03 01:14

配列で受け取った値からSQL文を生成するのですが、未入力の場合と「0」の場合での分岐が上手くいきません。

$_POSTの中身

Array ( [name] => テスト三郎 [入社年月日] => 2019-03-21 [zip_code] => [address] => [line_id] => 3 [shift_flag] => 0 [退職年月日] => )

上記データに対して、

PHP

1foreach($_POST as $k=>$v): 2 if($v): 3 $text = $text.",`$k`='$v'"; 4 else: 5 $text = $text.",`$k`=NULL"; 6 endif; 7endforeach; 8echo $text;

とすると、

,`name`='テスト三郎',`入社年月日`='2019-03-21',`zip_code`=NULL,`address`=NULL,`line_id`='3',`shift_flag`=NULL,`退職年月日`=NULL

となります。
shift_flag のところはNULLではなく、「shift_flag='0'」としたいのですが・・・。

if($v)ではなく、if(!is_null($v))、if(!empty($v))、if(!is_set($v))等も試しましたが意図した挙動にはなりません。

フォームから値が送信されてきていないもの、と、「0もしくはその他の値が送信されてきたもの」の2種類に切り分けるにはどのようにすればよいのでしょうか・・・。

※$textの頭にある「,」はこのあと取り除き、「UPDATE into **** SET」に置き換えます。
※そもそも$_POST配列のキーとDBのカラム名が一致しているので、もっと簡単なUPDATE方法がありますかね???

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

これはWHERE句の仕様ですか?
ユーザーから受け取った文字列を利用してカラムを埋め込むのはNGです
(管理画面や自分専用を除く)
また中身が空文字""のときにNULLと比較してしまうのでまったくだめです
そもそもNULLを検出する演算子は等号ではなくisです

sample

ちゃんとやるなら最低限こうしてください

PHP

1<?PHP 2$shift_flag=filter_input(INPUT_POST,"shift_flag"); 3$is_null=filter_input(INPUT_POST,"is_null",FILTER_DEFAULT,FILTER_REQUIRE_ARRAY)?:[]; 4$set=""; 5$data=[]; 6if(in_array("shift_flag",$is_null)){ 7 $set.=",shift_flag = null"; 8}elseif(!is_null($shift_flag)){ 9 $set.=",shift_flag = ?"; 10 $data[]=$shift_flag; 11} 12print $set."<br>"; 13print_r($data); 14?> 15<script> 16window.addEventListener('DOMContentLoaded', function(e){ 17 [].forEach.call(document.querySelectorAll('[name="is_null[]"]'),function(x){ 18 x.addEventListener('change',function(e){ 19 document.querySelector('[name="'+e.target.value+'"]').disabled=e.target.checked; 20 }); 21 }); 22}); 23</script> 24<form method="post"> 25シフトフラグ:<input type="text" name="shift_flag" value="0" id="shift_flag"> 26<label><input type="checkbox" name="is_null[]" value="shift_flag">null</label><br> 27<input type="submit" value="send"></form>

さらにバリデートを厳密に適用するならこう

PHP

1<?PHP 2$shift_flag=filter_input(INPUT_POST,"shift_flag",FILTER_VALIDATE_INT); 3$is_null=filter_input(INPUT_POST,"is_null",FILTER_DEFAULT,FILTER_REQUIRE_ARRAY)?:[]; 4$set=""; 5$data=[]; 6 7if(in_array("shift_flag",$is_null)){ 8 $set.=",shift_flag = null"; 9}elseif($shift_flag===false){ 10 print "error"; 11}elseif(!is_null($shift_flag)){ 12 $set.=",shift_flag = ?"; 13 $data[]=$shift_flag; 14} 15print $set."<br>"; 16print_r($data); 17?> 18<script> 19window.addEventListener('DOMContentLoaded', function(e){ 20 [].forEach.call(document.querySelectorAll('[name="is_null[]"]'),function(x){ 21 x.addEventListener('change',function(e){ 22 document.querySelector('[name="'+e.target.value+'"]').disabled=e.target.checked; 23 }); 24 }); 25}); 26</script> 27<form method="post"> 28シフトフラグ:<input type="text" name="shift_flag" value="0" id="shift_flag" pattern="\d+" required> 29<label><input type="checkbox" name="is_null[]" value="shift_flag">null</label><br> 30<input type="submit" value="send"></form>

投稿2019/06/03 01:31

編集2019/06/03 03:49
yambejp

総合スコア114572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Take_it

2019/06/03 01:47

UPDATEのSET句の部分です。 WHERE句でNULL検出はおっしゃる通り ``***` IS NULL `ですが・・・。 >ユーザーから受け取った文字列を利用してカラムを埋め込むのはNGです というのは、 >ユーザーから受け取った文字列を`そのままカラムに埋め込む`のはNGです という意味ですよね。 こちらには特に記載はしておりませんが、入力段階でのバリデーションと、この前段階でも$_POSTに対して一応のバリデーションは施してあります。管理画面です。
m.ts10806

2019/06/03 02:36

>こちらには特に記載はしておりませんが、入力段階でのバリデーションと、この前段階でも$_POSTに対して一応のバリデーションは施してあります。管理画面です。 横から失礼しますが、バリデーションとSQLのエスケープは別物です。 バリデーションはSQLインジェクションを防ぐ対策にはなりません。
yambejp

2019/06/03 03:21

update構文のset句処理ならバルクで処理して insert on duplicate key updateで処理するとよいでしょう。 なお、空("")とNULLは違うので、post値が空だとNULLは 絶対やってはいけません。 やるならis_nullチェックボックスみたいなものをつくって チェックされているときはnullという処理が必要です
Take_it

2019/06/03 03:59

空("")とNULLが違うというのは理解していますが、、 formにおいて、入力が必須の項目と必須ではない項目があり、必須ではない項目は未入力のまま送信を許可しています。 すると、$_POSTではその項目は空("")になります。 別にこれを、空のままMySQLに放り込んでもいいんですが、そうすると、その項目が未設定か否かを判別する際に、IS NULL だけでは判別ができなくなりますよね。 未設定の場合はデータベース上 NULL にしといたほうが、後々楽だと思ったのですが。。 「絶対にやってはいけない」のは、何故でしょうか・・・?
yambejp

2019/06/03 04:05 編集

> 「絶対にやってはいけない」のは、何故でしょうか・・・? 空なのとNULLなのはロジックがまったく異なるためです (とくに文字列系の場合) int系のカラムでnullは集計の際に極端に負担が高くなります nullが発生するような場合は正規化して別テーブルをつくり 存在するデータのみ保存するなどの工夫をするとよいでしょう どうしても1テーブルで処理したいかつ0が存在するデータなら -1など使用しない適当な数値を空であると設定するか 0を入れておいて別途is_nullカラムをつくってからであることを 担保することです
maisumakun

2019/06/03 05:24

Oracleだと、文字列型の「空文字列」と「NULL」は区別しない、というすごい仕様になっています。
yambejp

2019/06/03 05:27

ああ、たしかにMySQLだとは一言も書いていないですね。 勝手にMySQLを想定して回答していました。
Take_it

2019/06/03 05:53

ごめんなさい。よく理解できてないです。 >空なのとNULLなのはロジックが全く異なる PHPにしろMySQLにしろ(今回の案件はMySQLです。明示してなくてすみません)、空とNULLがもつ意味合いが異なることは承知をしています。 しかし、どちらも「意味を持ったデータがそこには登録されていない」という意味合いでは同じことなので、だったら空にするかNULLにするか、どちらかに統一したほうが後々のメンテナンスを考えても容易だろうと思い、未設定・未定義の値はNULLで扱う事にしました。 そこまで「NULLを使うな」と言われると、逆にNULLの存在意義ってなんなのだろう・・・。
guest

0

ベストアンサー

0はfalseと判定されるのでそのようになっていますね。

boolean に変換する場合、次の値は FALSE とみなされます。

boolean の FALSE
integer の 0 (ゼロ)
float の 0.0 (ゼロ)
空の文字列、 および文字列の "0"
要素の数がゼロである 配列
特別な値 NULL (値がセットされていない変数を含む)
空のタグから作成された SimpleXML オブジェクト

なので、is_null,empty,issetでは対応できません。個別に0だったらを入れるのが確実です。

php

1 if($v || $v=='0'): 2 $text = $text.",`$k`='$v'"; 3 else: 4 $text = $text.",`$k`=NULL"; 5 endif;

他の項目にも0が入ってくる可能性があるのでしたら決め打ちするしかないと思います。

php

1$flags = ['shift_flag',]; //フラグ判断対象カラム 2 3foreach($_POST as $k=>$v): 4 if($v || in_array($k,$flags)): 5 $text = $text.",`$k`='$v'"; 6 else: 7 $text = $text.",`$k`=NULL"; 8 endif; 9endforeach; 10

投稿2019/06/03 01:20

編集2019/06/03 01:26
m.ts10806

総合スコア80765

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Take_it

2019/06/03 01:35

ご教示頂いた方法でひとまず解決致しました。 is_nullのような方法で一発でこれを判別する方法がなぜないのだろう。。
m.ts10806

2019/06/03 01:37

そこはPHPがもともと型の概念が緩かったからですね。 PHP7になって型宣言などもできるようになりましたが、 今回のようなケースは1つ1つ丁寧に指定してあげるしかないと思います。
guest

0

$a === $b のようにして、$a が $b に等しく、および同じ型である場合に TRUE にすれば0とNULLを区別できるかもしれませんよ。

空文字とかNULLとか0とか

投稿2019/06/03 01:25

ices_sinon

総合スコア479

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問