PHPのinstanceofでclassの比較判定を行う方法

20/01/11 16:59:58     20/01/11 16:59:58

オブジェクトの元のクラスを判定し、判定結果に応じて処理を切り替えるようなことがあります。

こういったロジックで活躍するのがinstanceofです。instanceofはオブジェクトとクラスの間に記述し、それによって前後のオブジェクトとクラスが一致しているかどうかを判定できます。

instanceof で判定を行う

さっそくinstanceof を使用したサンプルコードです。

<?php
class Foo {}
class Bar {}

function sample($obj){
    if($obj instanceof Foo){
        return "foo";
    } else if($obj instanceof Bar){
        return "bar";
    } else {
        return "";
    }
}

$foo = new Foo();
$bar = new Bar();
echo sample($bar);

このコードを実行すると、以下のように出力されます。

bar

$fooを渡した場合はfooが、$barを渡した場合barが入る仕様になっています。instanceofでオブジェクトとクラスを比較し、if文とelse if文で分岐させています。

ちなみにinstanceofはオブジェクトだけに使えるものなので、他の変数などの判定に使用することはできません。上記のコードではクラスオブジェクトとクラスを比較しましたが、クラスオブジェクト同士を比較したり、クラスを代入した変数と比較することもできます。

instanceofは変数には使用できないということでしたが、クラスが格納されている場合は例外です。サンプルコードは以下になります。

$bar1 = new Bar();
$bar2 = new Bar();

var_dump($bar1 instanceof $bar2); // TRUE

$str = 'Bar';
var_dump($bar1 instanceof $str); // TRUE

また少し応用的な使い方として、そのクラスオブジェクトがインターフェイスを実装しているかどうか判定することもできます。サンプルコードは以下です。

<?php
interface SampleInterface {}
class Foo implements SampleInterface{}

$foo = new Foo();
var_dump( $foo instanceof SampleInterface ); // TRUE

まずインターフェイスを宣言し、それを実装したクラスを宣言します。クラスオブジェクトを作成し、そのオブジェクトがインターフェイスを実装しているかどうかをinstanceofで判定しています。

その他の型チェック

instanceofでクラスオブジェクトを判定するだけでなく、その他のデータ型などのチェックが必要なケースもあるかもしれません。せっかくなので、その他の型チェックコードも紹介しておきます。

gettype()でプリミティブ型・組み込み型のデータ型の判定

gettype()を使用すると、引数の型を判定することができます。instanceofのように比較するものではありませんが、変数の型を調べるときなどに使用するかもしれません。基本となる使い方は以下です。

gettype(123456789);
// => 'integer'
gettype('abcdefghijklmn');
// => 'string'

この例では数値と文字列を直接格納していますが、もちろん変数に格納してから引数に変数を指定することも可能です。gettypeは引数がどの型かを文字列で返す関数ですが、特定の型かどうかをチェックして、戻り値にtrueかfalseを返す関数も複数用意されています。

具体的には以下のようなものです。is_scalar()、is_string()、is_numeric()、is_bool()、is_array()、is_null()、などがあります。

get_class()でオブジェクトの型をチェックする

get_classはinstanceofによく似た関数です。どちらもオブジェクトに対して使用する点では共通していますが、instanceofが比較に使用するのに対し、get_classはどのオブジェクト型かを文字列で返すという点に違いがあります。

サンプルコードは以下です。

$d = new DateTime();
get_class($d);
// => 'DateTime'

$zip = new ZipArchive();
get_class($zip);
// => 'ZipArchive'

それぞれオブジェクトを作成し、get_classで判定しています。そうすると、もとのクラスが文字列で返されました。

is_a()で親クラスも含めたクラス、インスタンスをチェックする

is_aはget_classよりもinstanceofによく似た関数です。サンプルコードは以下です。

class Dog {
}
$d = new Dog();
is_a($d, Dog);
// => true

class SpecialDog extends Dog {
}
$d = new SpecialDog();
is_a($d, Dog);
// => true

instanceofはオブジェクトとクラスをinstanceofの前後に記述しましたが、is_aはそれぞれ第一引数と第二引数に指定します。またクラスオブジェクトをクラスと対比させた際に一致すればtrueとなりますが、親クラスと対比させた場合も一致すればtrueとなります。

上の例だとDog→SpecialDog→dとそれぞれクラスとオブジェクトがありますが、この場合dはDogに対してもSpecialDogに対してもis_aを使えばtrueとなります。

method_exists()でメソッドがあるかどうかをチェックする

少しオブジェクトやクラスの話とは異なりますが、使い方が似たものとしてメソッドの存在チェックができるmethod_exists()があります。サンプルコードは以下です。

class Dog {
    public function bow() {
    }
    private function bowwow() {
    }
}

$d = new Dog();
method_exists($d, 'bow');
// => true

method_exists($d, 'bowwow');
// => true

第一引数がオブジェクト、第二引数がメソッドです。第一引数で指定したクラスオブジェクトのクラス内に第二引数で指定したメソッドが含まれていればtrueを返し、そうでない場合falseを返します。

またアクセス修飾子がpublicでもprivateでも同様に機能します。また、メソッドではなくクラス内にプロパティが存在するかどうかをチェックする場合property_exists()を使用します。引数の使い方はまったく同じです。

ReflectionMethodでメソッドのアクセス修飾子をチェック

最後に、メソッドのアクセス修飾子をチェックすることもできます。サンプルコードは以下です。

class Dog {
    protected function bowwow() {
    }
}

$check = new ReflectionMethod(Dog, 'bowwow');
$check->isPublic(); // => false
$check->isProtected(); // => true
$check->isPrivate(); // => false

ReflectionMethodのオブジェクトを生成し、それぞれ修飾子をチェックしています。一致するとtrue、一致しない場合falseを返します。

以上、クラスオブジェクトとクラスの比較や、それに類似する判定、比較方法について紹介しました。

人気記事

編集部おすすめ記事

この記事を読んだ人はこんな記事を読んでいます

案件探しやフリーランスになるための相談する