W3docs

Object Oriented Programming with PHP Interfaces

Interfaces are a fundamental part of Object Oriented Programming (OOP) in PHP, and they play an important role in helping to ensure that code is well organized,

An interface is a contract that lists the methods a class must provide, without saying how those methods work. It lets unrelated classes agree on a shared set of behaviors, so the rest of your code can depend on the contract rather than on any specific class. This chapter covers how to declare interfaces, implement them, use constants, extend and combine interfaces, and the common pitfalls to avoid.

If you are new to objects, read PHP Classes and Objects and What is OOP in PHP first.

What is an Interface in PHP?

An interface defines a set of public method signatures — names, parameters, and (optionally) return types — but no method bodies. Any class that implements the interface promises to supply a concrete body for every one of those methods. If it does not, PHP throws a fatal error.

Because the interface only states what a class can do and never how, you can swap one implementation for another without touching the code that uses them. That decoupling is the whole point.

<?php
interface Logger {
  public function log(string $message): void;
}

Key rules for interface members:

  • All methods are implicitly public and abstract — you cannot give them bodies, and you cannot mark them private or protected.
  • An interface may declare constants, but not properties.
  • A class signals that it fulfills the contract with the implements keyword.

Why Use Interfaces?

  • Contracts. They guarantee that any implementing class exposes an agreed-upon API, so callers know exactly which methods are available.
  • Loose coupling. Code can be written against the interface (Logger) instead of a concrete class (FileLogger), so you can switch implementations freely — a real file logger in production, a fake one in tests.
  • Multiple types. Unlike class inheritance, a class can implement many interfaces, letting it play several roles at once.
  • Polymorphism. Different objects that share an interface can be used interchangeably wherever that interface is expected.

Implementing an Interface

Use the implements keyword followed by the interface name, then provide a body for every method the interface declares.

<?php
interface Logger {
  public function log(string $message): void;
}

class ConsoleLogger implements Logger {
  public function log(string $message): void {
    echo "[LOG] {$message}\n";
  }
}

$logger = new ConsoleLogger();
$logger->log('App started');
// Output: [LOG] App started

ConsoleLogger honors the Logger contract, so anywhere your code expects a Logger you can pass a ConsoleLogger.

Type Hinting Against an Interface

The biggest payoff comes when you type-hint the interface rather than a concrete class. The function below works with any Logger, so you can change implementations without rewriting it.

<?php
interface Logger {
  public function log(string $message): void;
}

class ConsoleLogger implements Logger {
  public function log(string $message): void {
    echo "[LOG] {$message}\n";
  }
}

class SilentLogger implements Logger {
  public function log(string $message): void {
    // intentionally does nothing
  }
}

function runJob(Logger $logger): void {
  $logger->log('Job finished');
}

runJob(new ConsoleLogger()); // Output: [LOG] Job finished
runJob(new SilentLogger());  // Output: (nothing)

Implementing Multiple Interfaces

A class can implement several interfaces at once by separating their names with commas. This is how PHP works around the lack of multiple class inheritance.

<?php
interface Drawable {
  public function draw(): string;
}

interface Serializable {
  public function toArray(): array;
}

class Circle implements Drawable, Serializable {
  public function __construct(private float $radius) {}

  public function draw(): string {
    return "Circle(r={$this->radius})";
  }

  public function toArray(): array {
    return ['type' => 'circle', 'radius' => $this->radius];
  }
}

$c = new Circle(2.5);
echo $c->draw() . "\n";          // Output: Circle(r=2.5)
echo json_encode($c->toArray()); // Output: {"type":"circle","radius":2.5}

Interface Constants

Interfaces can hold constants, which every implementing class inherits. They are useful for shared, fixed values that belong to the contract.

<?php
interface HttpStatus {
  const OK = 200;
  const NOT_FOUND = 404;
}

class Response implements HttpStatus {
  public function notFound(): int {
    return self::NOT_FOUND;
  }
}

$r = new Response();
echo $r->notFound();        // Output: 404
echo HttpStatus::OK;        // Output: 200

Extending Interfaces

One interface can build on another with extends, and unlike classes, an interface may extend multiple interfaces at once. A class implementing the child interface must satisfy all inherited methods.

<?php
interface Readable {
  public function read(): string;
}

interface Writable {
  public function write(string $data): void;
}

interface ReadWrite extends Readable, Writable {}

class Memory implements ReadWrite {
  private string $buffer = '';

  public function read(): string {
    return $this->buffer;
  }

  public function write(string $data): void {
    $this->buffer .= $data;
  }
}

$m = new Memory();
$m->write('hello ');
$m->write('world');
echo $m->read(); // Output: hello world

Checking for an Interface

Use the instanceof operator to confirm an object honors a given contract before calling its methods.

<?php
interface Logger {
  public function log(string $message): void;
}

class ConsoleLogger implements Logger {
  public function log(string $message): void {
    echo $message . "\n";
  }
}

$obj = new ConsoleLogger();
var_dump($obj instanceof Logger); // Output: bool(true)

Interface vs. Abstract Class

They overlap but solve different problems:

InterfaceAbstract class
Method bodiesNo (only signatures)Yes (can mix concrete + abstract)
PropertiesNo (constants only)Yes
How many per classMany (implements A, B)One (extends A)
Use it whenUnrelated classes share a capabilityRelated classes share code and state

Reach for an interface to describe a capability; reach for an abstract class to share partial implementation among related classes. If you need to share method bodies across unrelated classes, see PHP Traits.

Common Pitfalls

  • Missing a method. Forgetting to implement even one interface method triggers a fatal error at class declaration.
  • Narrowing visibility. Interface methods are public; you cannot implement them as protected or private.
  • Changing the signature. The implementing method's parameters and return type must stay compatible with the interface, or PHP raises an error.
  • Expecting properties. Interfaces declare behavior, not data — they cannot contain properties, only constants.

Conclusion

Interfaces let you program to a contract instead of a concrete class: they define what a class must do, support multiple implementations, and make polymorphism, testing, and refactoring far easier. Combine them with inheritance and traits to design flexible, maintainable PHP applications.

Practice

Practice
What is the primary use of PHP interfaces according to the page from W3Docs?
What is the primary use of PHP interfaces according to the page from W3Docs?
Was this page helpful?