Although I have a good knowledge of the PHP API and object oriented programming concepts, I learned something very interesting about interfaces in PHP. You probably know that an interface can extend another interface like a class does with another class. But, did you know that an interface can extend multiple interfaces in a row unlike classes? I didn't until today. I just discovered thanks to one of the best contributors of the Symfony2 framework: Bernhard Schussek aka WebMozart (love his nickname by the way :) ).
What are interfaces?
Interfaces are kind of abstract classes that only declare the public API. The public API is composed of constants and public methods. Unlike an abstract class that can contain abstract and concrete methods (private, protected and public altogether), an interface can only contain public methods signatures as shown below.
interface UserInterface { const FLAG_SUPER_ADMIN = 0; const FLAG_ADMIN = 1; const FLAG_USER = 2; public function getUsername(); public function getPassword(); public function getSalt(); }
In the above example, we declare a UserInterface interface that defines
three constants and methods. If an abstract or concrete class implements this
interface, it will have to implements the three methods with their body.
The role of an interface is to force a class to implement a certain public API
provided by the interface. The interface can also give a type to a class. For
example, if we define a concrete LdapUser class that implements the
UserInterface, an object of the LdapUser class will be typed as with both
LdapUser and UserInterface types.
var_dump($user instanceOf LdapUser); // returns true var_dump($user instanceOf UserInterface); // returns true
An interface can also extend another interface as it's explained in the following section.
Single Interface Inheritance
Interfaces behave like real abstract and concrete classes when it comes to inheritance. An interface can extend another interface as you can see in the following example.
interface AdvancedUserInterface extends UserInterface { function isActivated(); function hasExpired(); }
If a LdapUser class implements the AdvancedUserInterface, an object of
this class will be typed with LdapUser, UserInterface and
AdvancedUserInterface.
var_dump($user instanceOf LdapUser); // returns true var_dump($user instanceOf UserInterface); // returns true var_dump($user instanceOf AvancedUserInterface); // returns true
Let's talk about the most unknown part of interfaces: multiple interfaces inheritance.
Multiple Interfaces Inheritance
Unlike classes, an interface can in fact extend several interfaces at a time.
Suppose, we would like the AdvancedUserInterface to extend the
UserInterface and also to have some ACL features like groups and roles. We
can of course put ACL methods directly in the AdvancedUserInterface
interface but we would probably like to attach the same ACL methods to another
user object that belongs from another class, which doesn't implement the
AdvancedUserInterface but only the UserInterface interface.
The best solution is to create a dedicated AccessControlListInterface and
make the AdvancedUserInterface extend both UserInterface and
AccessControlListInterface interfaces.
interface AccessControlListInterface { function getGroups(); function getRoles(); function addGroup($group); function addRole($role); function hasRole($role); } interface AdvancedUserInterface extends UserInterface, AccessControlListInterface { function isActivated(); function hasExpired(); }
Finally, the LdapUser class can only implement the AdvancedUserInterface
interface to take benefit from the UserInterface and AccessControlList
APIs.
class LdapUser implements AdvancedUserInterface, Iterator { // Implement UserInterface methods // Implement AdvancedUserInterface methods // Implement AccessControlListInterface methods // Implement Iterator methods }
Finally, the LdapUser class implements all methods from the three previous
interfaces plus the Iterator interface methods.



Posté par Geoffrey - Il y'a environ about 1 year
Posté par Timothée - Il y'a environ about 1 year
What if two interfaces share the same method prototype ? Or worst, what if they share the declaration of the same constant with different values ?
I know it's tricky, but it's one of the reasons why we can't extend two classes, for the best, don't get me wrong.
Posté par Bernhard - Il y'a environ about 1 year
"Fatal error: Cannot inherit previously-inherited or override constant FOO from interface B"
"Fatal error: Can't inherit abstract function B::foo() (previously declared abstract in A)"
Posté par Serge HARDY - Il y'a environ 11 months
One of the main advantages of the use of interface is the "interface segregation principle" (the I in SOLID) which forces you to make dependencies at the highest level