浜松のWEBシステム開発・スマートフォンアプリ開発・RTK-GNSS関連の開発はお任せください
株式会社シーポイントラボ
TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:静岡県浜松市中区富塚町1933-1 佐鳴湖パークタウンサウス2F

【PHP】7.2 より前のバージョンの PHP では is_object 関数に object を渡しても false になる場合がある

 題の通り7.2 より前のバージョンの PHP では is_object に object を渡しても false になる場合があります。私的にこれは直感的でない挙動で、他の多くの方もそう思ったのか PHP 7.2 以降でこの動作はなくなりました。
 これが起きる例は次です。

<?php
// あるクラスをシリアライズ
class Hoge {
    
}

$a = new Hoge();
echo serialize($a);// O:4:"Hoge":0:{}
var_dump(is_object($a));// bool(true)
<?php
// シリアライズ元がないクラスでアンシリアライズ
$b = unserialize('O:4:"Hoge":0:{}');
var_dump($b);
//object(__PHP_Incomplete_Class)#1 (1) {
//  ["__PHP_Incomplete_Class_Name"]=>
//  string(4) "Hoge"
//}
var_dump(is_object($b));
// if(PHPのバージョン >= 7.2.0) {
//    bool(true)
// } else {
//    bool(false)
// }

Online PHP editor | output for LTdrs
 シリアライズ元はobjectであり、アンシリアライズ後もクラス未定義によるクラスのインスタンスですがobjectです。しかし、is_object関数にかけるとfalseになります。このため、PHP 7.1以前のバージョンでオブジェクトか否かを7.2以降的、言い換えれば直感的に識別するならば次の様にするべきです。

<?php
/**
 * PHP 7.2.0 以降の is_object の挙動をする関数
 * @param mixed $value 検証対象の値
 * @return bool
 */
function is_object_like_72($value)
{
    return is_object($value) || $value instanceof __PHP_Incomplete_Class;
}

$b = unserialize('O:4:"Hoge":0:{}');
var_dump($b);
/*
object(__PHP_Incomplete_Class)#1 (1) {
  ["__PHP_Incomplete_Class_Name"]=>
  string(4) "Hoge"
}
*/
var_dump(is_object($b));// false
var_dump(is_object_like_72($b));// true

 is_object に加えて特例も判定するのみです。
 この is_object に object を渡しても false になる挙動が現れる PHP バージョンは既にサポート終了ですが、やんごとなき理由で触らなければいけない時は多々あります。またこれはオートローダや適切なロード先を読み込む前に片っ端からアンシリアライズする様な処理で引っ掛かりやすいです。そういったものがあると頭の片隅に入れておくと役に立つかもしれません。

 ちなみに PHP の公式ドキュメントにはしっかり記載があります。
PHP: is_object – Manual

バージョン 説明
7.2.0 クラス定義が存在せず (__PHP_Incomplete_Class クラス)、
かつシリアライズ化されていないオブジェクトに対して、
is_object() 関数は true を返すようになりました。
これより前のバージョンでは、false を返していました。
  • この記事いいね! (0)