How do I know if a class implements an interface?

Asked

Viewed 687 times

9

In PHP, we can implement one (or more) interface in a class.

Thus:

  interface Authenticable {
       // métodos
  }

  interface Model {
      // métodos
  }

  class Person implements Authenticable, Model {
     // métodos
  }

In the above example, Person implements Authenticable and Model.

How could I check to see if a certain class implements an interface? For example, how to know that a particular instance of Person implements Authenticable?

Note: I always use versions of PHP 5.4 >=. So it would be preferable a more up-to-date form possible for such an operation.

2 answers

10


The operator shall be used instanceof:

interface Authenticable {
     // métodos
}
interface Model {
    // métodos
}
class Person implements Authenticable, Model {
   // métodos
}
$pessoa = new Person();
if ($pessoa instanceof Model) echo "implementa Model";
if ($pessoa instanceof Cloneable) echo "implementa Cloneable";

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

It is not what you want and in a few situations it is useful (I think only if you are doing some helper tool), but if you prefer can list everything:

interface Authenticable {
     // métodos
}
interface Model {
    // métodos
}
class Person implements Authenticable, Model {
   // métodos
}
$pessoa = new Person();
print_r(class_implements($pessoa));

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

  • 1

    Right, that’s right +1. Now I wonder if instanceof was a correct approach of PHP to detect interfaces

1

To know which interfaces a class implements, just use the function SPL class_implements()

Scope

array class_implements ( mixed $class [, bool $autoload = true ] )

From PHP 5.1 you can set the class name to string:

$rs = class_implements('Foo');
var_dump($rs);

We can use instanceof as a more practical means, but you need to make sure that the instance is an interface, otherwise you can create an inconsistency by returning extended class instead of interfaces. Moreover, with instanceof it is assumed that you already know the name of the interfaces. With class_implements() an array of names of the implemented objects is returned. It is most useful for when you do not know which objects are implemented.

These are the objects we will use for testing:

interface iFoo {
}

class Bar {
}

class Foo implements ifoo {
}

class Foo2 extends Bar {
}

Test with class_implements()

$rs = class_implements('Foo');
var_dump($rs);
/*
array(1) {
  ["iFoo"]=>
  string(4) "iFoo"
}
*/

$rs = class_implements('Foo2');
var_dump($rs);
/*
Foo2 é uma instância de Bar, porém, não retorna ao invocar class_implements() por ser uma class e não uma interface. O resultado nesse caso é vazio.

array(0) {
}
*/

Test with instanceof

O uso do `instanceof` pode causar inconsistência. Veja o exemplo:

$c = new Foo;
if ($c instanceof iFoo) {
    echo 'yes';
} else {
    echo 'no';
}
/*
iFoo é uma interface. O retorno é 'yes'.
*/

$c = new Foo2;
if ($c instanceof Bar) {
    echo 'yes';
} else {
    echo 'no';
}

/*
Bar() não é uma interface, mas ainda assim retorna 'yes' porque instanceof não distingue se o objeto é uma class ou uma interface.
Isso é um exemplo de inconsistência.
*/

It’s good to make it clear that I don’t mean it’s wrong to use instanceof for such purpose (within the context of the question), provided that the exceptions are observed.

However, it is good to highlight the inconsistency when indicating the use of instanceof for this purpose. For security, use the most consistent, the function class_implements().

Reflection?

I would rather not even comment use of Reflection because, for static tasks, it makes no sense to use OOP classes.

But if you already have an instance of Reflectionclass(), can take advantage of it to get a list of interfaces that the object implements:

$rs = new ReflectionClass('Foo');
var_dump($rs->getInterfaces());
/*
array(1) {
  ["iFoo"]=>
  object(ReflectionClass)#2 (1) {
    ["name"]=>
    string(4) "iFoo"
  }
}
*/

Reference: http://php.net/manual/en/reflectionclass.getinterfaces.php

Note: In the examples above show only how to abstract the data. No need to show how to use if else, in_array() and things like, to take the name of an object that might be present in the result. After all, whoever is reading this must already know how to use such basic things.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.