面向接口编程本质是用契约代替实现,通过职责清晰、命名明确的接口解耦业务代码,如userrepositoryinterface、usernotifierinterface等,配合依赖注入与psr-4自动加载实现可替换、易测试的最小闭环。

PHP 面向接口编程 + PSR 规范,本质是用契约代替实现,让业务代码不再“粘连”在具体类上。关键不在写多少 interface,而在于接口是否真实反映职责、命名是否清晰、使用是否贯穿整个调用链。
定义接口要贴合业务语义,不为接口而接口
接口不是技术摆设,而是对“能做什么”的明确承诺。比如用户注册流程中,不要定义一个笼统的 UserManager,而应拆解为:
-
UserRepositoryInterface:只负责数据存取(
save()、findById()) -
UserNotifierInterface:只负责通知动作(
sendWelcomeEmail()、sendSmsCode()) -
UserValidatorInterface:只负责校验逻辑(
isValidEmail()、isPasswordStrong())
每个接口名带 Interface 后缀,符合 PSR-12 建议;方法名用动宾结构,不暴露实现细节(如不用 sendEmailViaSMTP())。
实现类与接口严格一对一,禁止“一接口多职责”
一个接口只允许一个核心实现类承担其全部契约。例如:
-
UserRepositoryInterface→EloquentUserRepository(Laravel 场景) -
UserNotifierInterface→MailgunNotifier(第三方邮件服务) -
UserValidatorInterface→DefaultUserValidator(基础规则)
若需替换实现(如测试时用 InMemoryUserRepository),只需新写一个类实现同一接口,无需改任何调用方代码。这是解耦落地的最小闭环。
依赖注入时只依赖接口,不 new 具体类
控制器或服务类中,构造函数参数必须声明为接口类型,并通过容器自动解析:
class UserRegistrationService
{
public function __construct(
private UserRepositoryInterface $repo,
private UserNotifierInterface $notifier,
private UserValidatorInterface $validator
) {}
}
不写 new EloquentUserRepository(),也不在方法内 use 实现类。这样单元测试时可直接传入 mock 对象,业务逻辑完全脱离数据库、网络等外部依赖。
自动加载与目录结构按 PSR-4 显式映射
接口和实现类需物理分离,但又通过命名空间保持语义关联。推荐结构:
src/ ├── Contracts/ ← 所有 Interface 放这里 │ ├── UserRepositoryInterface.php │ ├── UserNotifierInterface.php ├── Repositories/ │ └── EloquentUserRepository.php ├── Notifiers/ │ └── MailgunNotifier.php
在 composer.json 中声明:
"autoload": {
"psr-4": {
"App\Contracts\": "src/Contracts/",
"App\Repositories\": "src/Repositories/",
"App\Notifiers\": "src/Notifiers/"
}
}
运行 composer dump-autoload 后,AppContractsUserRepositoryInterface 就能被自动加载,无需手动 require。
不复杂但容易忽略:接口不是装饰,它必须被真正使用——从定义、注入、到测试,每个环节都指向同一个契约。一旦形成习惯,换数据库、切通知渠道、加新校验规则,都只是新增一个实现类的事。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











