PHP接口是强制契约,必须用interface关键字定义且被implements显式实现;禁止属性和方法体,仅允许public方法声明与const常量;类型检查唯一可靠方式是instanceof。

PHP接口不是“可选语法糖”,而是强制契约:只要用了 interface,就必须被 implements 显式实现,且方法一个都不能少——否则直接 Fatal error 中断执行。
interface 定义必须用关键字,不能写成 class 或 trait
这是最常踩的语法坑。有人复制类定义习惯,把 class MyInterface 当成接口写法,结果 PHP 解析器立刻报 Parse error: syntax error。interface 是独立语法结构,和 class、trait 并列,三者命名空间互斥。
-
interface PaymentInterface✅ 正确 -
class PaymentInterface❌ 解析失败 -
trait PaymentInterface❌ 同样报错
接口里只允许:public 方法声明(不写修饰符也默认 public)、const 常量;禁止属性、构造函数、静态方法体(PHP 8.0+ 允许声明 static function,但依然不能写实现)。
implements 必须显式写出,且所有方法签名要严格匹配
PHP 不支持隐式实现。哪怕你类里恰好有 pay() 和 refund() 两个方法,只要没写 implements PaymentInterface,$obj instanceof PaymentInterface 就是 false —— 这和 Go 的鸭子类型完全不同。
立即学习“PHP免费学习笔记(深入)”;
- 多个接口用逗号分隔:
class Alipay implements Payable, Refundable, Loggable - 缺一个方法就报:
Fatal error: Class Alipay contains abstract method ... and must therefore be declared abstract - 参数名可以不同,但类型、数量、默认值必须兼容(比如接口声明
pay(float $amount = 0.0),实现类不能删掉= 0.0,也不能改成int $amount) - 两个接口若都定义了同名方法但签名冲突(如参数类型不一致),PHP 编译期直接拒绝
接口中不能写方法体,但可用 abstract 类 + final 方法模拟复用
原生 interface 里加 default 关键字会直接解析失败——PHP 不支持 Java 那套默认方法语法。想复用通用逻辑(比如统一日志前缀),得绕道:
- 定义
interface Notifiable声明notify(string $message): void - 建
abstract class BaseNotifier,里面写final public function notify(...) - 具体类
class EmailService extends BaseNotifier implements Notifiable
这样既满足接口契约,又避免重复实现;final 防止子类覆盖,abstract 阻止被实例化。
类型检查必须用 instanceof,别用 get_class()
判断对象是否符合接口规范,唯一可靠方式是 $obj instanceof Notifiable。用 get_class($obj) 只能拿到类名,完全无法反映接口实现关系——哪怕它实现了十个接口,get_class() 也只返回一个字符串。
这点在依赖注入场景尤其关键:Laravel 的容器、自定义工厂类、测试 mock 对象,都依赖 instanceof 做运行时契约校验。漏掉这个,后期扩展或替换实现时容易静默失败。
接口方法签名兼容性、多接口方法名冲突、抽象基类与 final 方法的组合使用——这些地方一旦出错,往往不是 Warning,而是直接中断执行,调试时得盯紧 Fatal error 的提示位置。



















