Interfaces are useful tools for systems architects and are often used to prototype an Application Programming Interface (API). Interfaces don't contain actual code, but can contain names of methods as well as method signatures.
ConnectionAwareInterface identifies a method, setConnection(), which requires an instance of Connection as an argument:interface ConnectionAwareInterface
{
public function setConnection(Connection $connection);
}implements after the open line that defines the class. We have defined two classes, CountryList and CustomerList, both of which require access to the Connection class via a method, setConnection(). In order to identify this dependency, both classes implement ConnectionAwareInterface:class CountryList implements ConnectionAwareInterface
{
protected $connection;
public function setConnection(Connection $connection)
{
$this->connection = $connection;
}
public function list()
{
$list = [];
$stmt = $this->connection->pdo->query(
'SELECT iso3, name FROM iso_country_codes');
while ($country = $stmt->fetch(PDO::FETCH_ASSOC)) {
$list[$country['iso3']] = $country['name'];
}
return $list;
}
}
class CustomerList implements ConnectionAwareInterface
{
protected $connection;
public function setConnection(Connection $connection)
{
$this->connection = $connection;
}
public function list()
{
$list = [];
$stmt = $this->connection->pdo->query(
'SELECT id, name FROM customer');
while ($customer = $stmt->fetch(PDO::FETCH_ASSOC)) {
$list[$customer['id']] = $customer['name'];
}
return $list;
}
}ListFactory, contains a factory() method, which initializes any class that implements ConnectionAwareInterface. The interface is a guarantee that the setConnection() method is defined. Setting the type hint to the interface instead of a specific class instance makes the factory method more generically useful:namespace Application\Generic;
use PDO;
use Exception;
use Application\Database\Connection;
use Application\Database\ConnectionAwareInterface;
class ListFactory
{
const ERROR_AWARE = 'Class must be Connection Aware';
public static function factory(
ConnectionAwareInterface $class, $dbParams)
{
if ($class instanceof ConnectionAwareInterface) {
$class->setConnection(new Connection($dbParams));
return $class;
} else {
throw new Exception(self::ERROR_AWARE);
}
return FALSE;
}
}DateAware and TimeAware. In addition to defining the setDate() and setTime() methods, they both define setBoth(). Having duplicate method names is not an issue, although it is not considered best practice. The problem lies in the fact that the method signatures differ:interface DateAware
{
public function setDate($date);
public function setBoth(DateTime $dateTime);
}
interface TimeAware
{
public function setTime($time);
public function setBoth($date, $time);
}
class DateTimeHandler implements DateAware, TimeAware
{
protected $date;
protected $time;
public function setDate($date)
{
$this->date = $date;
}
public function setTime($time)
{
$this->time = $time;
}
public function setBoth(DateTime $dateTime)
{
$this->date = $date;
}
}setBoth() from one or the other interface. Alternatively, you could adjust the method signatures to match.In the Application/Database folder, create a file, ConnectionAwareInterface.php. Insert the code discussed in the preceding step 2.
Next, in the Application/Generic folder, create two files, CountryList.php and CustomerList.php. Insert the code discussed in step 3.
Next, in a directory parallel to the Application directory, create a source code file, chap_04_oop_simple_interfaces_example.php, which initializes the autoloader and includes the database parameters:
<?php
define('DB_CONFIG_FILE', '/../config/db.config.php');
require __DIR__ . '/../Application/Autoload/Loader.php';
Application\Autoload\Loader::init(__DIR__ . '/..');
$params = include __DIR__ . DB_CONFIG_FILE;The database parameters in this example are assumed to be in a database configuration file indicated by the DB_CONFIG_FILE constant.
You are now in a position to use ListFactory::factory() to generate CountryList and CustomerList objects. Note that if these classes did not implement ConnectionAwareInterface, an error would be thrown:
$list = Application\Generic\ListFactory::factory(
new Application\Generic\CountryList(), $params);
foreach ($list->list() as $item) echo $item . '';Here is the output for country list:

You can also use the factory method to generate a CustomerList object and use it:
$list = Application\Generic\ListFactory::factory(
new Application\Generic\CustomerList(), $params);
foreach ($list->list() as $item) echo $item . '';Here is the output for
CustomerList:

If you want to examine what happens when multiple interfaces are implemented, but where the method signature differs, enter the code shown in the preceding step 4 into a file, chap_04_oop_interfaces_collisions.php. When you try to run the file, an error is generated, as shown here:

If you make the following adjustment in the TimeAware interface, no errors will result:
interface TimeAware
{
public function setTime($time);
// this will cause a problem
public function setBoth(DateTime $dateTime);
}