Interfaces

Interfaces as contracts for testable, flexible architecture.

On this page

What an Interface Is

An interface defines a contract: what methods must exist, without dictating how they are implemented. Interfaces enable clean architecture and easy testing.

Basic Interface Example

<?php
interface Cache {
  public function get(string $key): ?string;
  public function set(string $key, string $value, int $ttlSeconds): void;
}

class ArrayCache implements Cache {
  private array $store = [];

  public function get(string $key): ?string {
    return $this->store[$key] ?? null;
  }

  public function set(string $key, string $value, int $ttlSeconds): void {
    $this->store[$key] = $value;
  }
}

Why Interfaces Help

Your service depends on the interface, not a concrete implementation. You can swap implementations (RedisCache, FileCache) without changing the service.

<?php
class ItemService {
  private Cache $cache;

  public function __construct(Cache $cache) {
    $this->cache = $cache;
  }

  public function hello(): string {
    $cached = $this->cache->get("hello");
    if ($cached) return $cached;

    $value = "Hello";
    $this->cache->set("hello", $value, 60);
    return $value;
  }
}

Testing with a Fake

For tests, you can pass a fake cache implementation.

<?php
$service = new ItemService(new ArrayCache());
echo $service->hello();

Production Tip

Use interfaces for boundaries that may change: storage, cache, HTTP clients, mailers. It keeps your codebase flexible and testable.