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

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

ただいまの
回答率

88.05%

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

解決済

回答 3

投稿 編集

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

score 320

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

$_POSTの中身

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

上記データに対して、

foreach($_POST as $k=>$v):
    if($v):
        $text = $text.",`$k`='$v'";
    else:
        $text = $text.",`$k`=NULL";
    endif;
endforeach;
echo $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方法がありますかね???

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+2

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

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

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

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

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

$flags = ['shift_flag',]; //フラグ判断対象カラム

foreach($_POST as $k=>$v):
    if($v || in_array($k,$flags)):
        $text = $text.",`$k`='$v'";
    else:
        $text = $text.",`$k`=NULL";
    endif;
endforeach;

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/06/03 10:35

    ご教示頂いた方法でひとまず解決致しました。

    is_nullのような方法で一発でこれを判別する方法がなぜないのだろう。。

    キャンセル

  • 2019/06/03 10:37

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

    キャンセル

+1

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

空文字とかNULLとか0とか

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

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

sample

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

<?PHP
$shift_flag=filter_input(INPUT_POST,"shift_flag");
$is_null=filter_input(INPUT_POST,"is_null",FILTER_DEFAULT,FILTER_REQUIRE_ARRAY)?:[];
$set="";
$data=[];
if(in_array("shift_flag",$is_null)){
  $set.=",shift_flag = null";
}elseif(!is_null($shift_flag)){
  $set.=",shift_flag = ?";
  $data[]=$shift_flag;
}
print $set."<br>";
print_r($data);
?>
<script>
window.addEventListener('DOMContentLoaded', function(e){
  [].forEach.call(document.querySelectorAll('[name="is_null[]"]'),function(x){
    x.addEventListener('change',function(e){
      document.querySelector('[name="'+e.target.value+'"]').disabled=e.target.checked;
    });
  });
});
</script>
<form method="post">
シフトフラグ:<input type="text" name="shift_flag" value="0" id="shift_flag">
<label><input type="checkbox" name="is_null[]" value="shift_flag">null</label><br>
<input type="submit" value="send"></form>


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

<?PHP
$shift_flag=filter_input(INPUT_POST,"shift_flag",FILTER_VALIDATE_INT);
$is_null=filter_input(INPUT_POST,"is_null",FILTER_DEFAULT,FILTER_REQUIRE_ARRAY)?:[];
$set="";
$data=[];

if(in_array("shift_flag",$is_null)){
  $set.=",shift_flag = null";
}elseif($shift_flag===false){
  print "error";
}elseif(!is_null($shift_flag)){
  $set.=",shift_flag = ?";
  $data[]=$shift_flag;
}
print $set."<br>";
print_r($data);
?>
<script>
window.addEventListener('DOMContentLoaded', function(e){
  [].forEach.call(document.querySelectorAll('[name="is_null[]"]'),function(x){
    x.addEventListener('change',function(e){
      document.querySelector('[name="'+e.target.value+'"]').disabled=e.target.checked;
    });
  });
});
</script>
<form method="post">
シフトフラグ:<input type="text" name="shift_flag" value="0" id="shift_flag" pattern="\d+" required>
<label><input type="checkbox" name="is_null[]" value="shift_flag">null</label><br>
<input type="submit" value="send"></form>

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/06/03 14:24

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

    キャンセル

  • 2019/06/03 14:27

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

    キャンセル

  • 2019/06/03 14:53

    ごめんなさい。よく理解できてないです。

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

    そこまで「NULLを使うな」と言われると、逆にNULLの存在意義ってなんなのだろう・・・。

    キャンセル

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

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

関連した質問

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