7のイベントを再登録するWindows7/8/10でRustを別ドライブに展開する際のTIPSPHP+SQLでMySQLのInnoDBのテーブルに複合キーかつ連番のINSERTを実装するネイティブなPHPでselectタグやradioボタンの選択状態をどう表現するかエンターキーによる入力項目のフォーカスの移動をWeb系システムに実装してみるCattleMute>PHP>PHPのempty()でゼロの取り扱いに対する注意、代替と対策2019.09.14PHPのempty()でゼロの取り扱いに対する注意、代替と対策PHPのempty()関数でゼロの取り扱いについては散々出尽くしているネタではあるが、システムを組んでいたときにempty()関数の恐ろしさに改めて気が付いた。CMSのテンプレートとかを作る際には非常に便利なempty()関数だが、システムでこいつを乱立させるとひどく痛い目にあう。多くの場合、配列が空きのときのチェックや、数字の絡まない文字列が空っぽのときのチェックに利用するのは良いものの、数値や論理値とかがチェックにかかってくる場合にはこれは絶対に使用してはならない。文字列型でもゼロが単一で入ってくる可能性がある場合も然り。いうか、意識してその部分に使わないようにしても、「気がついたら使っていた!あかんやんけ!」ってことはPHPでプログラムを組んでいる際にはよくある話だと思う。論理値でもfalseなら空っぽ、trueの場合は値が入っているとみなされるこんなことをしてもいずれも空として評価されてしまう。論理値(boolean)については内部的には「falseは0」であり「trueは1」であるといった形がPHPでは行われている。この値をempty()が評価している模様。'これはtrueです';こういった結果となるので、例えばある条件を満たした場合は空白や文字列型ゼロ等を入れ、そうでなければfalseを入れるといったものを評価に入れるといった方針をコーディング上で一貫しているなら、これについては特に問題とはならんと思う。脱線した話を挟んでしまったが、CMSだとempty()で評価される対象の変数やオブジェクトについては、多少乱暴な書き方をしたとしてもうまいこと処理されるようになっていたりする。いうか、テンプレートとかをわずかな知識で誰でも作れるようにするためか、そうなっているものが多い印象がある。システムを作る際には自分でGET/POSTメソッドの送信や、ひいてはSQL文などを全て自分で発行して処理しなければならない。その都合上、CMSの延長線の感覚でシステムを作ろうとして、パラメータ値やテーブルカラム値を判定する際にゼロを取り扱うところに(またはゼロが入ることを作り手である自分が予期できないところに)誤って使用してしまうと、ふとした所で「これおかしくね?何が原因??」となる。GET/POSTメソッドの場合は、直感的・視覚的にHTMLにvalueが入るため、比較的気付きやすく直しやすいが、特に問題になるのはSQLのクエリをPHPに落とし込んでくるとき。'当該の商品グループでは在庫がゼロのものはありません。'当該の商品グループで在庫がゼロになった商品があります';}}上記はempty()で評価する変数(SQL実行結果を格納)を単純にレコードの存在チェックだけに利用することを想定しているが、この変数に結果ゼロが入ってきた場合はメッセージは表示されない。(上例のように単純なものであるなら、変数にレコードが存在するかの判定にはそもそもisset()使えばええやんって話やけど・・・。)SQLだとデータベースのテーブル定義でINT型にしているところへ不特定多数のデータが入る場合、非常に気付きづらいし直しづらい。CMSで多少複雑なテーマを作れる程度で調子こいて、システムに同じ感覚でこういった条件の評価を乱立させると完全に収拾がつかない事態に発展する。(えらそーにいっている俺もその道は既に通っている。自分の場合は当該の関数がゼロのときは空判定することは過去の経験から知っていたものの、今回はSQL周りをガッツリ書いているときに不意打ちを食らった・・・。)というか、そもそもempty()だけでそういったデータを全て評価して処理しきろうというのも無理がある話ではある。同じことを行おうとしてもPHPは空っぽであることを判定できるのは、このempty()関数か、もしくはNULLを判定するisset()関数くらいしかない。代替と対策としてゼロをempty()の範囲外にするために、これを拡張してユーザ定義関数としてシステム上に突っ込んでおくことが肝要。false;}}手続き型のコーディングでもオブジェクト指向型のコーディングでも、とりあえずメインルーチンのファイルインクルードする際に別ファイルにしたこの関数を突っ込む。関数名はis_emptyでもvacantでもnullpoでも、PHPの定義済の関数や、将来的に実装されないと思われる関数の名前なら何でもいい。定義済の関数の拡張なのにわざわざこれをオブジェクト指向型に合うようにライブラリ化とかする必要もない。実際のところ、PHPは手続き型だろうが、オブジェクト指向型だろうが、どっかのタイミングで関数を使うことには変わらないのでこの程度でオッケー。後は、empty()を書いた部分でゼロを評価していそうなところをこのユーザ定義関数に置き換える。その箇所が多岐に渡って散見しているのであれば、開発段階ならいっそグレップして思考停止で全てを置き換えてしまってもいいかもしれない。́・ω・`)で、この際なのでこぼれ話。前回のこちらの記事でのブログ更新からだいぶ日が空いてからの更新になったけど、システムの案件で大きいものを正式に受注することになりました。仕事の出所はいつもやり取りしている人ではなく、完全にcattlemute個人で受けてきて、はっきり言っていつもやり取りしている人から受けるお仕事の遥か比ではない人と物と予算と時間が動きます。(胃が痛い・・・)ってか、大きい案件を正式に受注したってところで、物を作るってことのモチベーションは過去現在含めて最高潮であるんだけど・・・その際に気づいたこと。俺、やっぱりプログラムって嫌いだわ。プログラムで「ものづくり」することそのものは好きだけどね。手段と目的の分別って大事。今回のこの記事にしてもそうだけど、システム関係で遭遇したTIPSがかなり溜まっていて時間があれば書いていきたい・・・が。今現在、このシステムのために色んな意味でほぼ煮詰まった缶詰になっているんだよね。(昼時・夜時と空腹感を覚えながらも、三度の飯よりそのままただひたすらプログラム作っている時間が長くて、俺自身がそのまま干物になりそうだ・・・)悠長にブログなんか更新していて良いんだろうかwwwwカテゴリPHPこの記事のコメントコメントはないです。コメントをキャンセルメールアドレスが公開されることはありません。*サイト次回のコメントで使用するためブラウザーに自分の名前、メールアドレス、サイトを保存する。