PHPのNotice対策
久しぶりにサーバOSのバージョンを上げて、ついでにPHPのバージョンを5から7にした。
そうしたら今までに開発したアプリケーションが全然動かない。
ついでに、今まで見逃していたPHP Noticeが大量発生していた。
実はPHP4時代に、初めてPHPを触った時から気まぐれに機能を追加してきたので、
むちゃくちゃな内容がたくさんありすぎる。PHP4からPHP5にしたときは、
めんどくさいので、何の対策もしてこなかったのが致命的に辛い。
これから気が遠くなる作業が待っているが、備忘録としてここに対策を少しずつ記入していくことにする。
01. eregはもう対応しません。
はい。eregはもう対応しなくなりました。eregは5.3非推奨になっていて、7では削除されました。
eregの代わりに preg_matchを使おう。
ereg("\abc$") ↓ preg_match("/\abc$/");
02. explode listの組み合わせにはarray_pad
これまで
while( !feof( $fpym ) ) { $buffer = fgets($fpym, 1024); list($y[$cnt], $m[$cnt]) = explode(",",$buffer); $m[$cnt] = trim($m[$cnt]); $cnt++; }
なんてことをしていたけれども、多分最後のEOFとかで、
Undefined offset: 1
なんて怒られてしまう。なので、array_padで足りない配列を埋めよう。
list($y[$cnt], $m[$cnt]) = array_pad(explode(",", $buffer), 2, null);
03. 内部エンコーディング htmlspecialchars
これまで
$a = htmlspecialchars($b,ENT_QUOTES);
としていたが、昔の名残で 表示のエンコードはShift_JIS。
でも、内部ではUTF-8なので、何故か
exit signal Illegal instruction (4)
というエラーがでる。
そこで、無理矢理Sfhift_JISに変換する.
$a = htmlspecialchars($b,ENT_QUOTES, "Shift_JIS");
これは、スクリプトで一括置換してもよいかも。
04. $_REQUEST $_GET系は、issetで明示的に.
これまで
$a = $_REQUEST['aaa']
なんてことをやっていて、なかったら$a=""じゃないかとして処理をしていたけどだめ。
if ( isset($_REQUEST['aaa']) ) {
$R_a = $_REQUEST['aaa'];
}
ということをしないといけない。これ、自動化できないか。なんかできそう。
05. A session had already been started - ignoring session_start()
これは、セッションが重複してsession_start()が呼ばれたときに起きる。
if ( !isset( $_SESSION ) ) {
session_start()
}
にしよう。
もちろん終了するときも同様。
if( isset( $_SESSION ) ) {
session_destroy();
}
regenerateも一緒。
06. Undefined index 配列じゃないとき
$_REQUESTが結構増えてくると毎回 issetを使うのが面倒なので、関数かするとよい。まあ、htmlspecialcharsいれてもいいかもね。
/** $_REQUEST['aaa'];をいきなり使うと、Notice:Undefinedが発生するため、それを防ぐ. * 例えば、$_REQUEST['abc'];を取得したい場合はこんな感じ。 * $_R_abc = _R("abc"); * @param str $_REQUEST['XXX'];のXXXの部分。 * @return $_REQUEST['XXX'];のデータ.存在しない時は ""を返す. */ function _R( $str ) { /** {{{*/ if ( isset($_REQUEST[$str]) ) { return $_REQUEST[$str]; } else { return ""; } } /**}}}*/
変数もどこで宣言したのか、途中で副作用が怖い場合は、直前にこんな風にしたらとりあえずNoticeは消える。本当は最初にきちんと宣言してたらいんだけど。
/** 未使用の変数でも、""として再定義させる.Notice: undefined variable対策. * 例えばいきなり、 aaa($x,$y)としたら$xが存在しないので、Noticeがでるので、 * $x = _V("x"); $y= _V("y");とする. * 変更がどのように影響するか考えるのがややこしいとき対策. * もともと存在した場合はそのままその変数を返すので大丈夫. * @param $str 変数名 * @return $strのデータ.存在しない時は""を返す. */ function _V( $str ) { /** {{{ */ if ( isset(${$str}) ) { return ${$str}; } else { return ""; } } /**}}}*/
配列にこいつをかけても大丈夫かどうかは、まだ未検証。多分大丈夫だと思うけど。
→だめだった。
08で、追加の対策
08 Notice: Undefined index: XXXX の対策 配列の時
06. Undefined index 対策で多分できると記述したもののできなくて、Undefined indexが出た。
これの対策は厳しい。関数化させようと、引数に入れた時点でアウト。
基本的にemptyで対策をすればよいのだが、if を使うと、毎回参照する時点で何行も記述しないといけないのが面倒なので、参考演算子を使ってみた。
!empty($mintemperature[$i])?:$mintemperature[$i]="";//Notice: Undefined index対策
print $maxtemperature[$i];
こんな感じ。
PHP7だとこんなこともできる。
$a = $array['A'][$i]['B'] ?? '';