简介

Laravel 中的契约是指框架提供的一系列定义核心服务的接口(interface)。

例如,Illuminate\Contracts\Queue\Queue 契约定义了队列任务所需的方法,而 Illuminate\Contracts\Mail\Mailer 契约定义了发送电子邮件所需的方法。

框架对每个契约都提供了相应的实现。例如,Laravel 提供了具有各种驱动的队列实现和由 SwiftMailer 提供支持的邮件驱动实现。

所有的 Laravel 契约都有他们自己的 GitHub 库。这为所有可用的契约提供了一个快速参考指南,同时也可单独作为低耦合的扩展包给其他包开发者使用。

契约 VS. Facades

Laravel Facades 和辅助函数提供了一种使用 Laravel 服务的简单方法,即不需要通过类型提示并从服务容器中解析契约。在大多数情况下,每个 Facades 都有一个等效的契约。

不同于门面不需要在构造函数中进行类型提示,契约允许你在类中定义显式的依赖。一些开发者倾向于以契约这种方式明确地定义它们的依赖项,而其它开发者则更喜欢 Facades 带来的便捷。

对于大多数应用程序来说,不管是使用门面还是契约都可以。但是,如果你正在构建一个扩展包,为了方便测试,你应该强烈考虑契约。

何时使用契约

综上所述,使用契约或是 Facades 很大程度上归结于个人或者开发团队的喜好。不管是契约还是 Facades 都可以创建出健壮的、易测试的 Laravel 应用程序。如果你长期关注类的单一职责,你会注意到使用契约还是 Facades 其实没多少实际意义上的区别。

然而,你可能还是会有几个关于契约的问题。例如,为什么要使用接口?不使用接口会比较复杂吗?下面让我们谈下使用接口的原因:低耦合和简单性。

低耦合

首先,让我们来看一些高耦合缓存实现的代码。如下:

<?phpnamespace App\Orders;class Repository
{/*** 缓存实例。*/protected $cache;/*** 创建一个仓库实例。** @param  \SomePackage\Cache\Memcached  $cache* @return void*/public function __construct(\SomePackage\Cache\Memcached $cache)
{$this->cache = $cache;}/*** 按照 Id 检索订单** @param  int  $id* @return Order*/public function find($id)
{if ($this->cache->has($id))    {//}}
}

在这个类中,程序与给定的缓存实现高耦合。因为我们依赖于一个扩展包的特定缓存类。一旦这个扩展包的 API 被更改了,我们的代码就必须跟着改变。

同样的,如果我们想要将底层的的缓存技术( Memcached )替换为另一种缓存技术( Redis ),那又得再次修改这个 repository 类。而 repository 类不应该了解太多关于谁提供了这些数据或是如何提供的等等。

比起上面的做法,我们可以使用一个简单的、与扩展包无关的接口来改进我们的代码:

<?phpnamespace App\Orders;use Illuminate\Contracts\Cache\Repository as Cache;class Repository
{/*** 缓存实例。*/protected $cache;/*** 创建一个仓库实例。** @param  Cache  $cache* @return void*/public function __construct(Cache $cache)
{$this->cache = $cache;}
}

现在,更改之后的代码没有与任何扩展包甚至是 Laravel 耦合。而契约扩展包不包含任何实现和依赖项,你可以轻松地编写任何给定契约的替代实现,来实现不修改任何关于缓存消费的代码就可以替换缓存实现。

简单性

当所有 Laravel 的服务都使用简洁的接口定义,就很容易判断给定服务提供的功能。可以将契约视为说明框架功能的简洁文档。

除此之外,当依赖的接口足够简洁时,代码的可读性和可维护性会大大提高。比起搜索一个大型复杂的类中有哪些可用的方法,不如检索一个简单、 干净的接口来参考更妥当。

如何使用契约

Laravel 中的许多类型的类都是通过 服务容器 解析出来的,包括控制器、事件监听器、中间件、任务队列,甚至路由闭包。所以,要获得一个契约的实现,你只需要在被解析的类的构造函数中添加「类型提示」即可。

例如,看看这个事件监听器:

<?phpnamespace App\Listeners;use App\User;
use App\Events\OrderWasPlaced;
use Illuminate\Contracts\Redis\Database;class CacheOrderInformation
{/*** Redis 数据库实现。*/protected $redis;/*** 创建事件处理器实例。** @param  Database  $redis* @return void*/public function __construct(Database $redis)
{$this->redis = $redis;}/*** 处理事件。** @param  OrderWasPlaced  $event* @return void*/public function handle(OrderWasPlaced $event)
{//}
}

当事件监听器被解析时,服务容器会读取类的构造函数上的类型提示,并注入对应的值。

浅析 Laravel 底层原理:契约(Contracts)相关推荐

  1. 浅析laravel门面原理与实现

    Facade模式 描述:Facade模式要求一个子系统的外部与其内部的通信必须通过一个统一的Facade对象进行.Facade模式提供一个高层次的接口,使得子系统更易于使用. 意义:将一个系统划分成为 ...

  2. redis单线程原理___Redis为何那么快-----底层原理浅析

    redis单线程原理 redis单线程问题 单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性),即一个线程处理所有网络请求,其他模块仍用了多个线程. 1. 为什么说redis能够快速执行 ...

  3. 解析Laravel框架下的Contracts契约

    Contracts Laravel 的契约是一组定义框架提供的核心服务的接口, 例如我们在介绍用户认证的章节中到的用户看守器契约IllumninateContractsAuthGuard 和用户提供器 ...

  4. 浅析“分布式锁”的实现方式丨C++后端开发丨底层原理

    线程锁.进程锁以及分布式锁相关视频讲解:详解线程锁.进程锁以及分布式锁 如何高效学习使用redis相关视频讲解:10年大厂程序员是如何高效学习使用redis Linux服务器开发高级架构学习视频:C/ ...

  5. Laravel 底层是如何处理 HTTP 请求的?

    基于 Laravel 框架构建的 Web 应用处理 HTTP 请求的流程也是如此.所有 HTTP 请求都会被转发到单入口文件 public/index.php,处理 HTTP 请求的核心代码如下(忽略 ...

  6. 数据结构 — 浅析红黑树原理以及实现

    浅析红黑树原理以及实现 我们在上一篇博客认识到了平衡二叉树(AVLTree),了解到平衡二叉树的性质,其实平衡二叉树最大的作用就是查找,AVL树的查找.插入 和删除在平均 和 最坏情况下都是O(log ...

  7. react 八千字长文深入了解react合成事件底层原理,原生事件中阻止冒泡是否会阻塞合成事件?

    壹 ❀ 引 在前面两篇文章中,我们花了较大的篇幅介绍react的setState方法,在介绍setState同步异步时提到,在react合成事件中react对于this.state更新都是异步,但在原 ...

  8. PHP的依赖注入是干什么的?底层原理是什么?

    PHP的依赖注入是一种设计模式,它可以将对象的创建和它所依赖的对象的创建分离开来,从而降低对象之间的耦合性,提高代码的可测试性和可维护性. 底层原理是通过将一个类所需要的依赖通过构造函数.属性或者方法 ...

  9. 没有与参数列表匹配的 重载函数 getline 实例_面试题:方法重载的底层原理?...

    前语:微信改版后,大量读者还没养成点赞的习惯,如写得好,望大家阅读后在右下边"好看"处点个赞,以示鼓励!长期坚持原创真的很不容易,多次想放弃,坚持是一种信仰,专注是一种态度. 关于 ...

最新文章

  1. 检测实现OpenCV2.4.4实现Shi-Tomasi角点检测(goodFeaturesToTrack)
  2. 编写一个程序,打印输入中各个字符出现频度的直方图
  3. Vue 使用 prerender-spa-plugin 添加loading
  4. 图像处理时一些卷积核子函数的生成
  5. 我的世界java版袭击图片_我的世界:你mc“中毒”有多深?这8张图都能看懂,绝对是真爱粉...
  6. 文件上传漏洞——DVWA练习
  7. 高效率学习Java编程提升自我
  8. 通过Spring的BeanPostProcessor的 bean的后置处理器会拦截所有bean创建过程
  9. win7 VS2008 不需新建工程 命令行编译lua5.1.5
  10. Android 组件系列-----Activity初步
  11. “北京链安”近日更名为“中科链安”
  12. 数据库快照的工作方式
  13. python编写接口自动化脚本_简单的python http接口自动化脚本
  14. lamda表达式修改数据_正则表达式学习教程
  15. 315前瞻:哪些互联网消费领域今年可能上榜?
  16. element 问号提示_点击HTML页面问号出现提示框(附源码)
  17. 微软手环2服务器,数据狂的最爱 微软手环2评测
  18. RFC2833 - 用于DTMF数字信号、电话音和电话信号的RTP负载格式
  19. 超级好用easyexcel插件
  20. 休闲平台,何去何从?(1)

热门文章

  1. python反转字符串递归怎么理解_Python使用递归反转字符串
  2. jstack 命令详解
  3. 负载均衡的常见实现方式
  4. matlab plot 曲线类型
  5. 使用flask实现基于elasticsearch的web端搜索功能
  6. 蝙蝠变身吸血鬼js网页动画
  7. 阿里云【达摩院特别版·趣味视觉AI训练营】笔记1
  8. [轻量级RTSP服务]Linux|麒麟操作系统下实现屏幕|系统声音采集
  9. 视频转化成gif动画怎么操作?教你一招分分钟视频转gif
  10. 分布式场景下的并发安全问题,收割快手,字节,百度,美团的Offer之旅