let's create! WordPressサイト制作とメンテ/エラー対応から、PHP/CSS/javascriptプログラミング、動画・音・イラスト等制作まで扱うコラム

【PHP学習的な内容】emptyやis_nullなどで判定できないnull(String)の対応(preg_matchやstrpos?)

更新: 2023/11/20 2920文字

今回は、前回まで作っていた『GetSimple-CMSをヘッドレスにするシリーズ』で、ちょっと困ったことが起こったので、対策を紹介します。何かというと『$var=NULLはemptyやis_nullで判定できるけど、それに引っかからないnull』ってケース。さっそく状況や対策を見ていきましょう。

phpのnull判定ってどうやる?

まずは、null判定について軽く押さえます。厳密にNULLかどうかっていうと『is_null』あたりを使うと思います。ただしこれは文字列の0などをfalseにしてしまうので、empty(文字列/数値の0はtrueで空という判定になる)とは挙動が違います。

管理人がてきとうに検索したところ、qiita.で簡潔にまとめてくれている方がいたので、紹介します。また、PHPマニュアルでも『型の比較,== による比較,=== による厳密な比較』などが書いてあるので、こちらもご確認ください(今回は、ダンプしたところ型がわかってえらい目にあったので)。

空の変数をvar_dumpした場合の、nullの出力のされ方

ちょっとしたことなんですけど、今回のポイントになりそうなので取り上げます。 例えば、こんな感じで空の変数を作って、var_dumpしてみた場合。

こんな感じでnullが出ます。普通はこんな感じになるんですが、お次の本題では、ちょっとやっかいな出方をしていますので、押さえておいてください。

本題:空判定できないnullの件

で、本題に入ります。前回の記事の続きで、GetSimpleをjson出力できるように改造し、idを取ってそれに応じて記事を表示させる機能です。idがヒットしなかった場合($jsonが空の場合など)、indexを表示させる予定だったんですけど・・・

出ません(笑) var_dumpしたところ、空なのでnullが出ています。そのほかは、空要素にアクセスしたので『Warning:Trying to access array offset on value of type null 』が出ていますね。画像はセットされていないので代替画像がでているだけです。

上記では『if($json ==false){~処理~}』で書きましたが、『if(is_null($json)){~処理~}』『if(empty($json)){~処理~}』などで書いても、一切空判定されませんでした。空判定されないということは、idが無いときのindex出力ができないということです。 しかし、null出力され方がなんか違うので、対処方法はありそうです。

null(String)原因や対処法

原因:CURLOPT_RETURNTRANSFERをtrueにすると、nullも文字列で返ってくる

で、『string』というのがヒントになって、原因発見。設定してあるCURLOPT_RETURNTRANSFERですが、『true を設定すると、curl_exec() の戻り値を文字列で返す』という機能です。これは、『nullも文字列で返ってくる』というおまけつき。 『null』っていう文字列が入っているわけだから、emptyになるわけがないということです

対処法その1:strposでnull(文字列)があるか探す

いくつかやってみた中で、(厳密な対応かは別として)サックリ対処できそうなコードをご紹介。まずは『strpos(文字列内の部分文字列が最初に現れる場所を見つける)』を使ってnull文字列を判定します。$posというのが結果が格納されていて、『if ($pos === 0)』で判定します。

ポイントは『===』をつかうところ。入ってこない場合はfalseで、冒頭にこの文字列が入ってきた場合、『位置がint(0)』で戻ってきます。『===』だと数値0かどうかも判定してくれるからです(厳密な型の判定)。

対処法その2:正規表現マッチング(preg_match)

判定できたパターンその2が、正規表現マッチングでした。こちらもnull文字列を検索パターンにします。『/^null/』(キャレット(^)付、文字列の先頭にnull),『/null/』(文字列null)どちらでも判定できました。

対処法その3:(調査中)cURLのエラーハンドリング

まだ調査中でやってないんですけど、cURL関連でエラー判定に使えるものが色々あるみたいです。『curl_execの返り値で判定』『curl_errno(エラー番号)や curl_error(エラーメッセ)』『curl_getinfo(直近の転送に関する情報を取得)』あたりが使えそうな気がします。

あとがき・まとめ

  • phpでnull判定につかわれそうなempty,isset,is_nullは似ているが挙動が違う
  • curl_setoptでCURLOPT_RETURNTRANSFERをtrueにした場合は、nullの場合も文字列(string)で返ってくる
  • string型のnullは、単純にis_nullやemptyでも判定できない
  • strposやpreg_matchで判定はできたが、strposで冒頭に出る場合は型の比較も重要

まとめると、こんなところでしょうか。管理人は以前、お仕事で『厳密な型判定(===)をしなかったために、判定できず苦労した』みたいなケースがあったので、『string null』というのに何とか気づけました。当サイトをお読みのみなさんも、『判定に使いたい要素のデータ型』も意識してもらえればと思います。


【カテゴリ】- PHP
【タグ】- , ,

関連記事