Programster's Blog

Tutorials focusing on Linux, programming, and open source

PHP - The Importance of Actually Implementing The Interface

In PHP, it is often important to use the keywords implements [interface name], and not just implement the methods that interface requires. This is best demonstrated with an example.

The script below places a few objects of the SubObject class into a Container class, before trying to serialize the container into a JSON output string. Try reading it to determine what it should output before running it.

<?php

class SubObject
{
    private $m_name;
    private $m_value;


    public function __construct($name, $value)
    {
        $this->m_name = $name;
        $this->m_value = $value;
    }


    public function jsonSerialize()
    {
        return array(
            'name' => $this->m_name,
            'value' => $this->m_value
        );
    }
}

class Container implements JsonSerializable
{
    private $m_subObjects = array();

    public function __construct(SubObject ...$subObjects) 
    { 
        $this->m_subObjects = $subObjects; 
    }

    public function jsonSerialize()
    {
        return $this->m_subObjects;
    }
}

$settings = array(
    new SubObject('host', 'www.google.com'),
    new SubObject('port', 3306),
);

$settingsContainer = new Container(...$settings);

print json_encode($settingsContainer, JSON_PRETTY_PRINT);

The code above will produce the following output:

[
    {},
    {}
]

However, if you just add the words implements JsonSerializable to the SubObject class (not having to change its body in any way as it already has the jsonSerialize method), then the script will now output what you might have expected:

[
    {
        "name": "host",
        "value": "www.google.com"
    },
    {
        "name": "port",
        "value": 3306
    }
]

With this simple example, you may wonder why a slip up would occur in the first place. However, just bear this in mind if you start developing a more complex codebase with multiple levels of composition, inheritance and interfaces.

It is worth remembering that even though a class can only extend just one other class, it can implement multiple interfaces. Also an interface can extend multiple other interfaces, like below:

interface a
{
    public function foo();
}

interface b
{
    public function bar();
}

interface c extends a, b
{
    public function baz();
}

References