Laravel 面向接口编程(实践)
面向接口编程是编码中的一种设计思想,这种方式基于接口而不是固定的类来构建应用程序。
如果您是一名程序员,那么您可能听说过则这样的说法,例如:面向接口编程、使用抽象类代替固定类等等。
这些都是说的同一件事,编写应用程序代码时,使其依赖抽象接口而不是具体的类。
为什么?
这是我第一次听到这句话时的确切反应。为什么要使用接口而不是类?即使创建了接口,我也需要创建一个实现该接口的类。这不是浪费时间吗?
当然不是!!
这个世界上唯一不变的就是变化本身,也就是说,变化是永恒的。
就编程而言,这同样没有例外。业务需求随着时间变化,我们的代码也要随之变化。
所以代码必需保持灵活。
面向接口编程可以使代码松散耦合且灵活。
怎么做?
观察下面的代码。
class Logger { public function log($content) { //日志保存到文件中. echo "Log to file"; } }
这是一个将日志记录到文件的简单类。 我们可以在控制器中调用它。
class LogController extends Controller { public function log() { $logger = new Logger; $logger->log('Log this'); } }
但如果需要将日志记录到多个地方 (如数据库,文件,云端等) 时,我们又该怎么办呢。
然后我们可以更改 LogController 和 Logger 类以适应这些更改。
class Logger { public function logToDb($content) { //将日志记录到 db. } public function logToFile($content) { //将日志保存到 file. } public function logToCloud($content) { //将日志存储到 cloud. } }
class LogController extends Controller { public function log() { $logger = new Logger; $target = config('log.target'); if ($target == 'db') { $logger->logToDb($content); } elseif ($target == 'file') { $logger->logToFile($content); } else { $logger->logToCloud($content); } } }
现在我们可以记录不同的目标了。但是,如果我们想将其他目标 (例如日志) 添加到 redis 服务器,该怎么办?最后,我们将同时修改 Logger 类和 LogController 类。
如您所见,这很快就摆脱了我们的控制,并且代码变得混乱。Logger 类很快成为一个整体。这是一场噩梦。
因此,我们需要拆分事物。遵循 SOLID 原则,我们可以将职责移至相应的类。
class DBLogger { public function log() { //将日志记录到 db } } class FileLogger { public function log() { //将日志保存到 file } } class CloudLogger { public function log() { //将日志存储到 cloud } }
并且控制器更改为:
class LogController extends Controller { public function log() { $target = config('log.target'); if ($target == 'db') { (new DBLogger)->log($content); } elseif ($target == 'file') { (new FileLogger)->log($content); } else { (new CloudLogger)->log($content); } } }
这样就好多了。现在如果要添加其他日志记录目标,我们可以创建一个新类并将其添加到 Controller 中的 if-else。
但是,我们的控制器仍然负责选择记录器。对于控制器,不需要知道不同的记录器并在它们之间进行选择。它只需要一个带有 log() 方法的记录器类来记录内容。
使用接口
这种情况就适合使用接口。那么什么是接口?
接口是对对象可以执行的操作的描述。
以我们的示例为例,控制器仅需要带有 log() 方法的记录器类。因此,我们的接口必须描述它必须具有 log() 方法。
interface Logger { public function log($content); }
如您所见,它仅包含函数声明,而不包含其实现,这就是为什么将其称为抽象的原因。
实现接口时,实现接口的类必须提供接口中定义的抽象方法的实现细节。
在我们的示例中,任何实现 Logger 接口的类都必须提供抽象方法 log () 的实现细节。
然后,我们可以在控制器中注入此接口。
class LogController extends Controller { public function log(Logger $logger) { $logger->log($content); } }
现在,控制器不再关心传递给它的记录器类型。它需要知道的是它必须实现 Logger 接口。
因此,我们需要修改 Logger 类以实现此接口。
class DBLogger implements Logger { public function log() { //将日志记录到 db } } class FileLogger implements Logger { public function log() { //将日志存储到 file } } class CloudLogger implements Logger { public function log() { //将日志保存到 cloud } }
现在,我们可以添加更多记录器,而无需触及现有代码。我们要做的就是创建一个实现 Logger 接口的新类。
class RedisLogger implements Logger { public function log() { //将日志存储到 redis } }
我们的代码现在看起来就变得灵活,低耦合了,我们可以随时改变实现方式而不用去改动之前的代码。
依赖注入
当我们使用的是 Laravel 框架,我们可以使用服务容器去自动注册接口的实现。
因为 Laravel 提供开箱即用的方法注入,所以我们只需要把接口和实现绑定起来。
首先我们需要创建一个 logger 的配置文件。 就像这样
<?php return [ 'default' => env('LOG_TARGET', 'file'), 'file' => [ 'class' => App\Log\FileLogger::class, ], 'db' => [ 'class' => App\Log\DBLogger::class, ], 'redis' => [ 'class' => App\Log\RedisLogger::class, ] ];
然后在 app/Providers 路径下 AppServiceProvider.php 的文件添加如下代码
class AppServiceProvider extends ServiceProvider { public function register() { $default = config('log.default'); $logger = config("log.{$default}.class"); $this->app->bind( App\Contracts\Logger::class, // the logger interface $logger ); } }
这样做的效果是,从 logger.php 配置文件读取默认的 logger ,然后绑定到 Logger interface 。这样当我们使用 Logger interface ,容器将会帮我们解析并返回默认的 Logger 实例。
因为默认的 logger 是使用 env() 助手指定的,所以我们可以在不同的环境使用不同的 logger ,例如本地环境使用 file ,生产环境使用 db 。
总结
使用接口可以让我们写出低耦合的代码,提供一个抽象层。它允许我们随时改变实现方式。所以,尽可能将你的应用中可变的部分用面向接口的方式实现。
推荐教程:《PHP教程》
以上是Laravel 面向接口编程(实践)的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

session_start()iscucialinphpformanagingusersessions.1)ItInitiateSanewsessionifnoneexists,2)resumesanexistingsessions,and3)setsasesessionCookieforContinuityActinuityAccontinuityAcconActInityAcconActInityAcconAccRequests,EnablingApplicationsApplicationsLikeUseAppericationLikeUseAthenticationalticationaltication and PersersonalizedContentent。

Laravel和Yii的主要区别在于设计理念、功能特性和使用场景。1.Laravel注重开发的简洁和愉悦,提供丰富的功能如EloquentORM和Artisan工具,适合快速开发和初学者。2.Yii强调性能和效率,适用于高负载应用,提供高效的ActiveRecord和缓存系统,但学习曲线较陡。

MySQL函数可用于数据处理和计算。1.基本用法包括字符串处理、日期计算和数学运算。2.高级用法涉及结合多个函数实现复杂操作。3.性能优化需避免在WHERE子句中使用函数,并使用GROUPBY和临时表。

2024年必备的Laravel扩展包包括:1.LaravelDebugbar,用于监控和调试代码;2.LaravelTelescope,提供详细的应用监控;3.LaravelHorizon,管理Redis队列任务。这些扩展包能提升开发效率和应用性能。

Composer是PHP的依赖管理工具,通过composer.json文件管理项目依赖。1)解析composer.json获取依赖信息;2)解析依赖关系形成依赖树;3)从Packagist下载并安装依赖到vendor目录;4)生成composer.lock文件锁定依赖版本,确保团队一致性和项目可维护性。

在Laravel中集成Sentry和Bugsnag可以提高应用的稳定性和性能。1.在composer.json中添加SentrySDK。2.在config/app.php中添加Sentry服务提供者。3.在.env文件中配置SentryDSN。4.在App\Exceptions\Handler.php中添加Sentry错误报告。5.使用Sentry捕获并报告异常,并添加额外上下文信息。6.在App\Exceptions\Handler.php中添加Bugsnag错误报告。7.使用Bugsnag监

在Laravel中构建实时聊天应用需要使用WebSocket和Pusher。具体步骤包括:1)在.env文件中配置Pusher信息;2)设置broadcasting.php文件中的广播驱动为Pusher;3)使用LaravelEcho订阅Pusher频道并监听事件;4)通过PusherAPI发送消息;5)实现私有频道和用户认证;6)进行性能优化和调试。

EagerLoading可以解决Laravel中的N 1查询问题。 1)使用with方法预加载相关模型数据,如User::with('posts')->get()。 2)对于嵌套关系,使用with('posts.comments')。 3)避免过度使用,选择性加载,并按需使用load方法。通过这些方法,可以显着减少查询次数,提升应用性能。
