PHP interfaces, what are they and when should you use them?

John Richardson

A pragmatic software developer with ~ 10 years experience. PHP/Vue JS advocate.

@JRdevelop July 22, 2017

As a junior PHP developer, you could probably be forgiven if you have not yet stumbled across or made use of interfaces. As someone more senior, you’ve obviously not been keeping up. Interfaces have been around since PHP 5.0 and are now widely adopted in most well written libraries and applications. With that in mind, I’m sure you’d agree that it’s worth spending a couple of minutes to figure out what an interface is and when you might consider using one.

So, what is an interface?

Often described as a contract, an interface ensures that all implementing classes provide specific methods. In other words, if your class implements an interface, then it is promising to provide some specific functionality. This is useful if other classes are going to be using the class since they can be sure that certain features will be available.

When using an interface, implementing classes become interchangeable with one another. As an example, let’s imagine that ‘Class A’ & ‘Class B’ implement ‘Interface Z’ which enforces the method ‘helloWorld()’. ‘Class C’ accepts ‘Interface Z’ as a parameter & then calls the ‘helloWorld()’ method.

The two implementing classes (A & B) could have very different implementations, and as such the results from calling their ‘helloWorld()’ method could also be very different. This does not concern ‘Class C’. So long as the injected object implements ‘Interface Z’ , ‘Class C’ can utilise it.

Stay with me! Actual code examples are coming soon, but first…

How do interfaces differ from abstract classes?

If you are familiar with abstract classes, interfaces work in a vaguely similar way, providing a blueprint for classes which use them. This may sound confusing, as you are probably wondering why an interface is needed if an abstract class serves a similar purpose.

Well, abstract classes are normally used when you need to provide some basic, or common functionality which can then be extended or modified by derived classes. I like to think that an abstract class defines the core identity of a class. Any derived classes are of the same type. As an example, you may have an abstract ‘Animal’ class and a derived ‘Dog’ class. An interface on the other hand defines how the class will interact with the outside world, and can be used by a wide range of object types. As an example, you may have a ‘Moveable’ interface, which both ‘Animal’ and ‘Vehicle’ types can implement.

Additionally, it is not possible for a class to extend multiple abstract classes, whereas it is possible to implement multiple interfaces.

Recap/Notes:

  • An interface can be used to enforce a single method, or multiple methods. Also, just to reiterate, an interface defines what methods a class MUST have, but it is still possible to add additional methods outside of this enforcement.
  • In PHP an interface contains method declarations only – the method itself will be empty. This is in contrast to abstract classes, where it is possible to add some logic to methods which can then be overloaded/overridden in sub-classes.
  • An interface expresses a ‘HAS A’ relationship, while an abstract class expresses an ‘IS A’ relationship.

Example:

I find it’s often easier to understand these concepts when given something to look at, so here is an example which demonstrates usage of an interface.

This interface will enforce one method on the classes that implement it:

interface RendererInterface {
    public function render();
}

These classes implement the interface (and as such must contain a method named ‘render’):

class JsonRenderer implements RendererInterface {`

`    public function render() {`

`    }
}
class XMLRenderer implements RendererInterface {`

`    public function render() {`

`    }
}

Notice both classes contain the render method, if they did not, then an exception would be thrown. When using these classes throughout your application you can now be sure that each has a render method, and as such they become interchangeable. You could, as an example, do something similar to the below:

class blogPost {`

`    function __construct(RendererInterface $renderer) {
        $this->renderer = $renderer;
    }`

`    function render() {
        return $this->renderer->render();
    }
}

The above class now has the ability to render it’s contents in many different formats. This is made possible by injecting a ‘renderer’ class (which implements ‘RendererInterface’) into it. If you are unfamiliar with interfaces, you may also be unfamiliar with type-hinting.

In a nut-shell, type-hinting allows you to restrict a parameter to a specified type. This makes sense when the code used inside the function or class relies on the type of object passed in. Since we are assigning the object to a class property and then calling a specific method(render), our class is relying on the fact that the method exists. By typing-hinting the parameter to an object type of ‘RendererInterface’, it is possible to safely assume that the call to the render method(‘return $this->renderer->render()’) will be valid. As an added bonus, this now means that it’s possible to pass in absolutely any type of object, so long as it implements the interface.

Use of type hinting generally makes life easier for developers and those maintaining the code-base. Your IDE (if you are using a decent one) will have the ability to provide code completion, and it also self documents the parameter for developers working on the project in future; they instantly know that rendering the blogPost in a different format is as simple as creating a new class which implements the interface defined in the constructor.

In a dynamically-typed language are interfaces truly necessary?

Essentially the answer to that is no – they are not compulsory. You can remove the type-hint from the previous example to demonstrate this:

class blogPost {`

`    function __construct($renderer) {
        $this->renderer = $renderer;
    }`

`    function render() {
        return $this->renderer->render();
    }
}

PHP is dynamically typed (checks types at run-time) and as such allows ambiguous variables to be passed in such a way. Of course, if the ‘renderer’ did not have a ‘render’ method then our script would crash when executed. In a statically typed language however, providing a type would be compulsory (as types are required to be known at compile time). You could definitely argue that enforcing types in this way is the superior choice, as it means we catch errors upfront rather than once the code reaches production, for example.

So although it’s not a requirement, it’s still wise to use interfaces where possible. As an example, you may often find yourself spending a lot of time on manual validation, such as using the ‘isobject()’, or ‘methodexists()’ functions throughout your classes to verify that the correct type/object has been passed in. Using an interface with type-hinting removes the need for this manual work. It also makes the code easier to maintain (as mentioned earlier in the article).

Thanks for reading, and if you have any queries pop them in a comment below and I’ll get back to you ASAP.