🏠 Home / Hub

🐘 PHP Lesson 10 — Interfaces

← Back to PHP Menu  |  🏠 Hub

1. Interface ဆိုတာ ဘာလဲ?

Interface = method signatures (no implementation) — "contract" ချမှတ်ခြင်း
class တစ်ခုသည် interface implement လုပ်ရင် — ထဲမှာပါတဲ့ methods အကုန် implement ရမယ်
PHP မှာ class တစ်ခု — interface အများကြီး implements နိုင် (multiple interface)
<?php

// Interface — method signatures only, no body
interface Drawable {
    public function draw(): string;
    public function getColor(): string;
}

interface Resizable {
    public function resize(float $factor): void;
    public function getArea(): float;
}

// Class implements multiple interfaces
class Circle implements Drawable, Resizable {
    public function __construct(
        private float $radius,
        private string $color
    ) {}

    // Must implement ALL methods from Drawable
    public function draw(): string {
        return "Drawing a {$this->color} circle (r={$this->radius})";
    }

    public function getColor(): string { return $this->color; }

    // Must implement ALL methods from Resizable
    public function resize(float $factor): void {
        $this->radius *= $factor;
    }

    public function getArea(): float {
        return M_PI * $this->radius ** 2;
    }
}

class Square implements Drawable, Resizable {
    public function __construct(
        private float $side,
        private string $color
    ) {}

    public function draw(): string {
        return "Drawing a {$this->color} square ({$this->side}x{$this->side})";
    }

    public function getColor(): string { return $this->color; }
    public function resize(float $factor): void { $this->side *= $factor; }
    public function getArea(): float { return $this->side ** 2; }
}

$c = new Circle(5.0, "red");
$s = new Square(4.0, "blue");

echo $c->draw();       // "Drawing a red circle (r=5)"
$c->resize(2);
echo $c->getArea();    // ~314.16

// Type hinting with interface
function drawAll(Drawable ...$shapes): void {
    foreach ($shapes as $shape) {
        echo $shape->draw() . "\n";
    }
}

drawAll($c, $s);

2. Interface Extends Interface

<?php

interface Loggable {
    public function log(string $message): void;
}

interface Cacheable {
    public function cache(string $key, mixed $data): void;
    public function getFromCache(string $key): mixed;
}

// Interface can extend other interfaces
interface Repository extends Loggable {
    public function findById(int $id): ?array;
    public function findAll(): array;
    public function save(array $data): bool;
    public function delete(int $id): bool;
}

// Implement — must implement all: Loggable + Repository methods
class UserRepository implements Repository {
    private array $users = [];
    private array $logs  = [];

    public function log(string $message): void {
        $this->logs[] = date("Y-m-d H:i:s") . " — " . $message;
    }

    public function findById(int $id): ?array {
        return $this->users[$id] ?? null;
    }

    public function findAll(): array { return $this->users; }

    public function save(array $data): bool {
        $id = $data['id'] ?? count($this->users) + 1;
        $this->users[$id] = $data;
        $this->log("Saved user #$id");
        return true;
    }

    public function delete(int $id): bool {
        if (!isset($this->users[$id])) return false;
        unset($this->users[$id]);
        $this->log("Deleted user #$id");
        return true;
    }
}

$repo = new UserRepository();
$repo->save(['id' => 1, 'name' => 'Ko Ko', 'email' => 'ko@example.com']);
$repo->save(['id' => 2, 'name' => 'Ma Ma', 'email' => 'ma@example.com']);
print_r($repo->findAll());

3. Interface Constants

<?php

interface HttpStatus {
    const OK          = 200;
    const CREATED     = 201;
    const BAD_REQUEST = 400;
    const UNAUTHORIZED = 401;
    const NOT_FOUND   = 404;
    const SERVER_ERROR = 500;
}

interface ApiResponse extends HttpStatus {
    public function respond(mixed $data, int $status = self::OK): array;
    public function error(string $message, int $status = self::BAD_REQUEST): array;
}

class JsonResponse implements ApiResponse {
    public function respond(mixed $data, int $status = self::OK): array {
        return [
            'status'  => $status,
            'success' => $status < 400,
            'data'    => $data,
        ];
    }

    public function error(string $message, int $status = self::BAD_REQUEST): array {
        return [
            'status'  => $status,
            'success' => false,
            'error'   => $message,
        ];
    }
}

$api = new JsonResponse();
$api->respond(['user' => 'Ko Ko']);
// ['status' => 200, 'success' => true, 'data' => ['user' => 'Ko Ko']]

$api->error("User not found", HttpStatus::NOT_FOUND);
// ['status' => 404, 'success' => false, 'error' => 'User not found']

4. Interface vs Abstract Class

FeatureInterfaceAbstract Class
Method implementation❌ No✅ Can have concrete methods
PropertiesConstants only✅ Full properties
Multiple inheritance✅ implements many❌ extends one only
Constructor❌ Not allowed✅ Allowed
Access modifierspublic onlyAll (public/protected)
Use when"Can do" behavior contract"Is a" base implementation
// Rule of thumb:
// Interface = "can do" / "is able to" (Printable, Serializable, Drawable)
// Abstract  = "is a" base (Animal, Shape, Vehicle)
💡 A class can extends ONE abstract class AND implements MANY interfaces simultaneously!

5. Dependency Injection with Interfaces

<?php

// Interface-based DI — loosely coupled, easily testable

interface EmailSender {
    public function send(string $to, string $subject, string $body): bool;
}

interface SMSSender {
    public function sendSMS(string $phone, string $message): bool;
}

class SmtpEmailSender implements EmailSender {
    public function send(string $to, string $subject, string $body): bool {
        // Real SMTP logic...
        echo "SMTP: Sending email to $to\n";
        return true;
    }
}

class MockEmailSender implements EmailSender {
    public array $sent = [];
    public function send(string $to, string $subject, string $body): bool {
        $this->sent[] = compact('to', 'subject', 'body');
        return true;
    }
}

class UserService {
    public function __construct(private EmailSender $mailer) {}

    public function register(string $name, string $email): void {
        // save to DB...
        $this->mailer->send(
            $email,
            "Welcome!",
            "Hi $name, thanks for registering!"
        );
    }
}

// Production
$service = new UserService(new SmtpEmailSender());
$service->register("Ko Ko", "ko@example.com");

// Testing — swap implementation easily!
$mock = new MockEmailSender();
$testService = new UserService($mock);
$testService->register("Test", "test@example.com");
print_r($mock->sent);  // verify email was "sent"

← PHP 09  |  Next: PHP 11 → Traits →

📌 Study Checklist