Interfaces in PHP

Interfaces in PHP

If you’ve read my post about classes in PHP, then you should have a fair understanding of how those work. I didn’t go into too much detail because I would like to build upon what you read previously. Hopefully, we can get a good foundation for you to continue to learn.

I was at our Beckley office today, telling a co-worker about my previous post, and what instantiation meant. Her knowing it comes from the word instance, helped her understand it’s definition and how I was using it. The word interface may sound like a difficult concept to grasp, but it isn’t. Below is a simple interface and how you would use it.


<?php

interface PersonInterface {
    public function eat($food);
}

class Person implements PersonInterface {
    // . . .
    // above is the code from the previous example
    public function eat($food) {
        echo $this->name . ' is eating ' . $food;
    }
}

Everyone has to eat (at least I think they do) and some people get angry when they don’t eat. Eating, amongst other things, is required for a person to stay alive. In our interface, we defined a method (a function) called eat that accepts $food. We then change our Person class to implement the PersonInterface. Now the Person class MUST have an eat method.

Using interfaces may seem like an extra step, extra code, and a waste of time. I assure you they are not and I’ll do my best to explain why they are useful. Without the interface, you really won’t know what all the Person class will do. Now anytime you get a Person object, you can always call the eat method. When writing an extensive library, it can become easy to forgot to include some of the required methods for a class.

One class can implement multiple interfaces as shown below.


<?php
// . . . previous code above. includes PersonInterface.

interface BathroomInterface {
    public function poop();
    public function pee();
    public function washHands();
}

class Person implements PersonInterface, BathroomInterface {
    // . . . eat method and the construct.

    public function poop() {
        echo "I feel better.";
    }

    public function pee() {
        echo "Glad I didn't pee my pants";
    }

    public function washHands() {
        echo "Yes, I wash my hands.";
    }
}

Now the Person class implements two interfaces and has more methods. The same rule applies with the BathroomInterface as did the PersonInterface, the Person class MUST have a poop, pee, and washHands method.

Below is an example of all of it put together and how you may use it.


<?php
interface PersonInterface {
    public function eat($food);
}

interface BathroomInterface {
    public function poop();
    public function pee();
    public function washHands();
}

class Person implements PersonInterface, BathroomInterface {
    public $name;
    public $age;

    public function __construct($name, $age)
    {
        $this->name = $name;
        $this->age = $age;
    }

    public function eat($food) {
        echo $this->name . ' is eating ' . $food;
    }

    public function poop() {
        echo "I feel better.";
    }

    public function pee() {
        echo "Glad I didn't pee my pants";
    }

    public function washHands() {
        echo "Yes, I wash my hands.";
    }
}

$levi = new Person("Levi", 32);
$levi->eat("Chicken"); // OUTPUT: Levi is eating Chicken
$levi->poop(); // OUTPUT: I feel better.
$levi->washHands(); // OUTPUT: Yes, I wash my hands.

An interface is an agreement that the class will have those methods. You can also type hint your parameters for a method by using the name of an interface. You could also type hint your parameter using the name of a class, but then you are forever locked in (I’m exaggerating) to using that class, which will get messy. Leaving our Person example below is an example of a type hinted method with an interface.


<?php
interface TechnologyInterface {
    public function turnOn();  // This will turn on the device
    public function turnOff(); // This will turn off the device
}

class Television implements TechnologyInterface {
    public $power; // We will store the device's state (on or off) in this variable

    public function turnOn() {
        $this->power = 'on'; // Since we turned it on, $power property is now on
        echo "Tv is on!";
    }

    public function turnOff() {
        $this->power = 'off'; // Since we turned it on, $power property is now off
        echo "Tv is off. Read a book!";
    }
}

class RemoteControl {
    // Since this method accepts a TechnologyInterface type, we know it WILL have
    // turnOn and turnOff methods.
    public function powerButton(TechnologyInterface $device) {
        // First we check to see if the device is on.
        if($device->power == 'on') {
            // the device was on, so turn it off.
            $device->turnOff();
        } else {
            // okay, the device was off, turn it on.
            $device->turnOn();
        }
    }
}

// Here is how we may use this.
$tvBrand = new Television;
$remote = new RemoteControl;
$remote->powerButton($tvBrand);

Try and walk through the above logic in your head and figure out what will happen if the TV was off. I hope this example shows how you can use an interface to predict the methods you will need to use. We know anything that implements the TechnologyInterface will have those two methods, we can call those functions without worrying if they will exist, because they must.

I don’t want to beat a dead horse, so I’ll stop here. Feel free to email me with any questions you may have or if you need further explanation.