PHP 对象接口
概述
接口(Interface)定义了类必须实现的方法契约。使用 interface 声明,使用 implements 实现。一个类可以实现多个接口。
版本要求
- PHP 8.0+:接口方法可以有返回类型
- PHP 8.1+:接口常量支持 final
基础概念
接口声明与实现
php
<?php
declare(strict_types=1);
interface Serializable
{
public function serialize(): string;
public function unserialize(string $data): void;
}
interface Loggable
{
public function toLogString(): string;
}
class User implements Serializable, Loggable
{
public function __construct(
public readonly string $name,
public readonly string $email,
) {}
public function serialize(): string
{
return json_encode(['name' => $this->name, 'email' => $this->email]);
}
public function unserialize(string $data): void {}
public function toLogString(): string
{
return "User({$this->name}, {$this->email})";
}
}接口继承
接口可以继承其他接口,使用 extends。
php
<?php
declare(strict_types=1);
interface Renderable
{
public function render(): string;
}
interface ContainerRenderable extends Renderable
{
public function getChildren(): array;
}
class Panel implements ContainerRenderable
{
public function render(): string
{
return '<panel>' . implode('', $this->getChildren()) . '</panel>';
}
public function getChildren(): array
{
return [];
}
}语法与代码
接口常量
接口可以定义常量,自动为 public。
php
<?php
declare(strict_types=1);
interface CacheDriver
{
public const DEFAULT_TTL = 3600;
public const MAX_KEY_LENGTH = 255;
public function get(string $key): mixed;
public function set(string $key, mixed $value, ?int $ttl = null): bool;
public function delete(string $key): bool;
}接口 vs 抽象类对比
| 特性 | 接口 | 抽象类 |
|---|---|---|
| 多继承 | 可实现多个 | 只能 extends 一个 |
| 方法实现 | 无具体实现(PHP 8.0 前) | 可有具体实现 |
| 属性 | 不能(PHP 8.4 前) | 可以 |
| 常量 | 可以(public) | 可以(任何修饰符) |
| 构造函数 | 不能 | 可以 |
| 适用场景 | 定义能力/契约 | 共享代码+强制实现 |
详细说明
接口中的默认方法(PHP 8.0+)
php
<?php
declare(strict_types=1);
interface Entity
{
public function getId(): int;
// PHP 8.0+ 默认实现
public function isNew(): bool
{
return $this->getId() === 0;
}
}
class Product implements Entity
{
public function __construct(private int $id = 0) {}
public function getId(): int
{
return $this->id;
}
// isNew() 使用接口默认实现
}实现多个接口
php
<?php
declare(strict_types=1);
interface CountableItems
{
public function count(): int;
}
interface ArrayAccessible
{
public function toArray(): array;
}
class Collection implements CountableItems, ArrayAccessible
{
private array $items;
public function __construct(array $items)
{
$this->items = $items;
}
public function count(): int
{
return count($this->items);
}
public function toArray(): array
{
return $this->items;
}
}实战示例
事件监听器接口
php
<?php
declare(strict_types=1);
interface EventListener
{
public static function supports(string $eventType): bool;
public function handle(array $event): void;
}
class UserCreatedListener implements EventListener
{
public static function supports(string $eventType): bool
{
return $eventType === 'user.created';
}
public function handle(array $event): void
{
echo "User created: {$event['name']}\n";
}
}
class EventDispatcher
{
private array $listeners = [];
public function addListener(EventListener $listener): void
{
$this->listeners[] = $listener;
}
public function dispatch(string $type, array $data): void
{
foreach ($this->listeners as $listener) {
if ($listener::supports($type)) {
$listener->handle(array_merge($data, ['type' => $type]));
}
}
}
}注意事项
- 接口常量自动 public:不能声明为 private 或 protected
- 实现接口必须实现所有方法:除非父类已实现
- 接口不能有属性(PHP 8.4 前)
- 方法签名必须完全匹配:包括返回类型
最佳实践
- 接口小而专注:每个接口代表一种能力
- 接口隔离原则:不要定义"胖接口"
- 使用类型提示接口:函数参数使用接口类型
- 命名以 -able 结尾:如 Serializable、Loggable
进阶用法
调试与测试技巧
php
<?php
declare(strict_types=1);
// 单元测试辅助函数
function createTestResource(): mixed
{
return match (true) {
default => new stdClass(),
};
}
// 调试输出函数
function debugOutput(mixed , string = ''): void
{
= ? ": " : '';
.= print_r(, true);
fwrite(STDERR, . "\n");
}
// 性能基准测试
function benchmark(callable , int = 1000): float
{
= hrtime(true);
for ($i = 0; $i < $iterations; $i++) {
$fn();
}
return (hrtime(true) - $start) / 1e9;
}日志记录实践
php
<?php
declare(strict_types=1);
/**
* 简易日志记录器
*/
class SimpleLogger
{
private string $logFile;
private string $level = 'INFO';
public function __construct(string $logFile)
{
$this->logFile = $logFile;
}
public function info(string $message, array $context = []): void
{
$this->log('INFO', $message, $context);
}
public function warning(string $message, array $context = []): void
{
$this->log('WARNING', $message, $context);
}
public function error(string $message, array $context = []): void
{
$this->log('ERROR', $message, $context);
}
private function log(string $level, string $message, array $context): void
{
$timestamp = date('Y-m-d H:i:s');
$contextStr = $context ? ' ' . json_encode($context, JSON_UNESCAPED_UNICODE) : '';
$line = "[{$timestamp}] [{$level}] {$message}{$contextStr}\n";
file_put_contents($this->logFile, $line, FILE_APPEND | LOCK_EX);
}
}配置与环境检测
php
<?php
declare(strict_types=1);
// 环境检测工具
class EnvironmentChecker
{
public static function checkRequirements(array $requirements): array
{
$results = [];
foreach ($requirements as $name => $check) {
$results[$name] = is_callable($check) ? $check() : false;
}
return $results;
}
public static function getSystemInfo(): array
{
return [
'php_version' => PHP_VERSION,
'os' => PHP_OS,
'sapi' => PHP_SAPI,
'memory_limit' => ini_get('memory_limit'),
'max_execution_time' => ini_get('max_execution_time'),
'loaded_extensions' => get_loaded_extensions(),
];
}
}常见问题排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 连接超时 | 网络问题/配置错误 | 检查配置,增加超时时间 |
| 权限不足 | 文件/目录权限 | 使用 chmod/chown 修正 |
| 性能下降 | 索引缺失/数据量大 | 添加索引,优化查询 |
| 数据不一致 | 并发冲突/事务残留 | 使用锁机制和事务 |
| 内存溢出 | 大数据集/未释放资源 | 增大内存限制,分批处理 |
故障排除步骤
- 检查错误日志和异常信息
- 确认配置和环境是否正确
- 使用调试工具逐步排查
- 参考官方文档查找已知问题
版本兼容性说明
| 功能 | 最低版本 | 说明 |
|---|---|---|
| 基础功能 | PHP 8.1 | 本文档基准版本 |
| 只读属性 | PHP 8.1 | public readonly 修饰符 |
| 枚举类型 | PHP 8.1 | enum 类型和 match 表达式 |
| Fiber | PHP 8.1 | 协程/轻量级并发 |
| 命名参数 | PHP 8.0 | foo(arg_name: value) |
| 联合类型 | PHP 8.0 | `int |
| Null 安全运算符 | PHP 8.0 | $obj?->method() |
| 析构器 promotion | PHP 8.0 | __construct(public $x) |
php
<?php
declare(strict_types=1);
// 版本兼容性检测
function ensureVersion(string $minVersion): void
{
if (version_compare(PHP_VERSION, $minVersion, '<')) {
throw new RuntimeException(
sprintf('需要 PHP %s+, 当前版本: %s', $minVersion, PHP_VERSION)
);
}
}
ensureVersion('8.1.0');