【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マニュアルでも『型の比較,== による比較,=== による厳密な比較』などが書いてあるので、こちらもご確認ください(今回は、ダンプしたところ型がわかってえらい目にあったので)。
PHPでnull判定関数(isset, empty, is_null)の違い(qiita)
https://qiita.com/YutaManaka/items/94a6c4a1d19d88ce2e3a
PHP 型の比較表 (PHPマニュアル)
https://www.php.net/manual/ja/types.comparisons.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になるわけがないということです。
curl_setopt(phpマニュアル)
https://www.php.net/manual/ja/function.curl-setopt.php
対処法その1:strposでnull(文字列)があるか探す
いくつかやってみた中で、(厳密な対応かは別として)サックリ対処できそうなコードをご紹介。まずは『strpos(文字列内の部分文字列が最初に現れる場所を見つける)』を使ってnull文字列を判定します。$posというのが結果が格納されていて、『if ($pos === 0)』で判定します。
ポイントは『===』をつかうところ。入ってこない場合はfalseで、冒頭にこの文字列が入ってきた場合、『位置がint(0)』で戻ってきます。『===』だと数値0かどうかも判定してくれるからです(厳密な型の判定)。
strpos(PHPマニュアル)
https://www.php.net/manual/ja/function.strpos.php
対処法その2:正規表現マッチング(preg_match)
判定できたパターンその2が、正規表現マッチングでした。こちらもnull文字列を検索パターンにします。『/^null/』(キャレット(^)付、文字列の先頭にnull),『/null/』(文字列null)どちらでも判定できました。
preg_match(PHPマニュアル)
https://www.php.net/manual/ja/function.preg-match
対処法その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
【タグ】- cURL(PHP), GetSimple-CMSをヘッドレスにするシリーズ, PHP