An interface for abstraction & type-hinting

An interface in PHP provides a way to define a contract for a class, specifying methods that must be implemented without including any implementation details. It is particularly useful when you want to use type-hinting for parameters, ensuring that the objects passed to a function meet a specific structure.

Example

<?php
 
// Define the LoggerInterface
interface LoggerInterface
{
public function log(string $message): void;
}
 
// Implement the LoggerInterface in a class
class FileLogger implements LoggerInterface
{
private string $filePath;
 
public function __construct(string $filePath)
{
$this->filePath = $filePath;
}
 
public function log(string $message): void
{
file_put_contents($this->filePath, $message . PHP_EOL, FILE_APPEND);
}
}
 
class DatabaseLogger implements LoggerInterface
{
public function log(string $message): void
{
// Simulate database logging
echo "Logging to database: $message\n";
}
}
 
// A class that depends on the LoggerInterface
class UserService
{
private LoggerInterface $logger;
 
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
 
public function createUser(string $username): void
{
// Logic to create a user
$this->logger->log("User created: $username");
}
}
 
// Usage example
$fileLogger = new FileLogger('log.txt');
$userServiceWithFileLogger = new UserService($fileLogger);
$userServiceWithFileLogger->createUser('Hyunseung');
 
$dbLogger = new DatabaseLogger();
$userServiceWithDbLogger = new UserService($dbLogger);
$userServiceWithDbLogger->createUser('Hyunseung');
  1. Interface: LoggerInterface defines the contract (log method) that implementing classes must follow.
  2. Implementations: FileLogger logs messages to a file. DatabaseLogger simulates logging to a database.
  3. Type-Hinting: The UserService class requires a LoggerInterface implementation in its constructor, ensuring flexibility and abstraction.

Benefits of Using Interfaces:

  • Code Reusability: Functions and classes can work with any implementation of the interface.
  • Flexibility: Allows switching implementations without changing dependent code.
  • Type Safety: Ensures that the passed object adheres to the expected contract.