本篇文章给大家带来的内容是关于Larave框架下Contracts契约的解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

Contracts

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

以及框架自带的App\User模型所实现的IlluminateContractsAuthAuthenticatable契约。

为什么使用契约

通过上面几个契约的源码文件我们可以看到,Laravel提供的契约是为核心模块定义的一组interface。Laravel为每个契约都提供了相应的实现类,下表列出了Laravel为上面提到的三个契约提供的实现类。

契约 Laravel内核提供的实现类
IllumninateContractsAuthGuard IlluminateAuthSessionGuard
IlluminateContractsAuthUserProvider IlluminateAuthEloquentUserProvider
IlluminateContractsAuthAuthenticatable IlluminateFoundationAuthAuthenticatable(User Model的父类)

所以在自己开发的项目中,如果Laravel提供的用户认证系统无法满足需求,你可以根据需求定义看守器和用户提供器的实现类,比如我之前做的项目就是用户认证依赖于公司的员工管理系统的API,所以我就自己写了看守器和用户提供器契约的实现类,让Laravel通过自定义的Guard和UserProvider来完成用户认证。自定义用户认证的方法在介绍用户认证的章节中我们介绍过,读者可以去翻阅那块的文章。

所以Laravel为所有的核心功能都定义契约接口的目的就是为了让开发者能够根据自己项目的需要自己定义实现类,而对于这些接口的消费者(比如:Controller、或者内核提供的 AuthManager这些)他们不需要关心接口提供的方法具体是怎么实现的, 只关心接口的方法能提供什么功能然后去使用这些功能就可以了,我们可以根据需求在必要的时候为接口更换实现类,而消费端不用进行任何改动。

定义和使用契约

上面我们提到的都是Laravel内核提供的契约, 在开发大型项目的时候我们也可以自己在项目中定义契约和实现类,你有可能会觉得自带的Controller、Model两层就已经足够你编写代码了,凭空多出来契约和实现类会让开发变得繁琐。我们先从一个简单的例子出发,考虑下面的代码有什么问题:

1

2

3

4

5

6

7

8

class OrderController extends Controller

{

    public function getUserOrders()

    {

        $orders= Order::where('user_id', '=', \Auth::user()->id)->get();

        return View::make('order.index', compact('orders'));

    }

}

这段代码很简单,但我们要想测试这段代码的话就一定会和实际的数据库发生联系。也就是说, ORM和这个控制器有着紧耦合。如果不使用Eloquent ORM,不连接到实际数据库,我们就没办法运行或者测试这段代码。这段代码同时也违背了“关注分离”这个软件设计原则。简单讲:这个控制器知道的太多了。 控制器不需要去了解数据是从哪儿来的,只要知道如何访问就行。控制器也不需要知道这数据是从MySQL或哪儿来的,只需要知道这数据目前是可用的。

Separation Of Concerns 关注分离

Every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class.

每个类都应该只有单一的职责,并且职责里所有的东西都应该由这个类封装

接下来我们定义一个接口,然后实现该接口

1

2

3

4

5

6

7

8

9

10

11

12

interface OrderRepositoryInterface

{

    public function userOrders(User $user);

}

class OrderRepository implements OrderRepositoryInterface

{

    public function userOrders(User $user)

    {

        Order::where('user_id', '=', $user->id)->get();

    }

}

将接口的实现绑定到Laravel的服务容器中

1

App::singleton('OrderRepositoryInterface', 'OrderRespository');

然后我们将该接口的实现注入我们的控制器

1

2

3

4

5

6

7

8

9

10

11

12

13

class UserController extends Controller

{

    public function __construct(OrderRepositoryInterface $orderRepository)

    {

        $this->orders = $orderRespository;

    }

  

    public function getUserOrders()

    {

        $orders = $this->orders->userOrders();

        return View::make('order.index', compact('orders'));

    }

}

现在我们的控制器就完全和数据层面无关了。在这里我们的数据可能来自MySQL,MongoDB或者Redis。我们的控制器不知道也不需要知道他们的区别。这样我们就可以独立于数据层来测试Web层了,将来切换存储实现也会很容易。

链接:https://pan.baidu.com/s/1v5gm7n0L7TGyejCmQrMh2g 提取码:x2p5

免费分享,但是X度限制严重,如若链接失效点击链接或搜索加群 群号518475424

接口与团队开发

当你的团队在开发大型应用时,不同的部分有着不同的开发速度。比如一个开发人员在开发数据层,另一个开发人员在做控制器层。写控制器的开发者想测试他的控制器,不过数据层开发较慢没法同步测试。那如果两个开发者能先以interface的方式达成协议,后台开发的各种类都遵循这种协议。一旦建立了约定,就算约定还没实现,开发者也可以为这接口写个“假”实现

1

2

3

4

5

6

7

class DummyOrderRepository implements OrderRepositoryInterface

{

    public function userOrders(User $user)

    {

        return collect(['Order 1', 'Order 2', 'Order 3']);

    }

}

一旦假实现写好了,就可以被绑定到IoC容器里

1

App::singleton('OrderRepositoryInterface', 'DummyOrderRepository');

然后这个应用的视图就可以用假数据填充了。接下来一旦后台开发者写完了真正的实现代码,比如叫RedisOrderRepository。那么使用IoC容器切换接口实现,应用就可以轻易地切换到真正的实现上,整个应用就会使用从Redis读出来的数据了。

接口与测试

建立好接口约定后也更有利于我们在测试时进行Mock

1

2

3

4

5

6

7

8

9

10

11

12

13

public function testIndexActionBindsUsersFromRepository()

{   

    // Arrange...

    $repository = Mockery::mock('OrderRepositoryInterface');

    $repository->shouldReceive('userOrders')->once()->andReturn(['order1', 'order2]);

    App::instance('OrderRepositoryInterface', $repository);

    // Act...

    $response  = $this->action('GET', 'OrderController@getUserOrders');

        

    // Assert...

    $this->assertResponseOk();

    $this->assertViewHas('order', ['order1', 'order2']);

 }

总结

接口在程序设计阶段非常有用,在设计阶段与团队讨论完成功能需要制定哪些接口,然后设计出每个接口具体要实现的方法,方法的入参和返回值这些,每个人就可以按照接口的约定来开发自己的模块,遇到还没实现的接口完全可以先定义接口的假实现等到真正的实现开发完成后再进行切换,这样既降低了软件程序结构中上层对下层的耦合也能保证各部分的开发进度不会过度依赖其他部分的完成情况。

Larave框架下Contracts契约的解析的更多相关文章

  1. springMVC框架下JQuery传递并解析Json数据

    springMVC框架下JQuery传递并解析Json数据

  2. (转)springMVC框架下JQuery传递并解析Json数据

    springMVC框架下JQuery传递并解析Json数据 json作为一种轻量级的数据交换格式,在前后台数据交换中占据着非常重要的地位.Json的语法非常简单,采用的是键值对表示形式.JSON 可以 ...

  3. Laravel框架下路由的使用(源码解析)

    本篇文章给大家带来的内容是关于Laravel框架下路由的使用(源码解析),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 我的解析文章并非深层次多领域的解析攻略.但是参考着开发文 ...

  4. 解析基于keras深度学习框架下yolov3的算法

    一.前言 由于前一段时间以及实现了基于keras深度学习框架下yolov3的算法,本来想趁着余热将自己的心得体会进行总结,但由于前几天有点事就没有完成计划,现在趁午休时间整理一下. 二.Keras框架 ...

  5. 全面解析Pytorch框架下模型存储,加载以及冻结

    最近在做试验中遇到了一些深度网络模型加载以及存储的问题,因此整理了一份比较全面的在 PyTorch 框架下有关模型的问题.首先咱们先定义一个网络来进行后续的分析: 1.本文通用的网络模型 import ...

  6. 微服务下的契约测试(CDC)解读

    1. 前言 有近两周没有在公众号中发表文章了,看过我之前公众号的读者都知道,公众号中近期在连载<RobotFramework接口自动化系列课程>,原本计划每周更新一篇,最近由于博主在带一个 ...

  7. java集合框架之java HashMap代码解析

     java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...

  8. nodejs 中koa框架下的微信公众号开发初始篇

    最近在搞微信公众号开发,后端采用的是nodejs下的koa框架,初识后端的菜鸟,自己搞难度太大了,网上找了很多文章,采用的中间件大都是express框架下的,不过好在爬了许多坑之后总算看见点曙光了,遂 ...

  9. java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题

    一.java自定义注解相关知识 注解这东西是java语言本身就带有的功能特点,于struts,hibernate,spring这三个框架无关.使用得当特别方便.基于注解的xml文件配置方式也受到人们的 ...

随机推荐

  1. SQL Server温故系列(0):导航目录

    创建本系列博文通用库表及数据的 SQL 语句:下载 SQL Server温故系列(0):导航目录 SQL Server温故系列(1):SQL 数据操作 CRUD 之增删改合 SQL Server温故系 ...

  2. webpack中使用DefinePlugin来传递构建的环境变量给源代码使用

    最近在思考如何提供一种前后端开发功能测试既高效又安全的方案,因为对于我平时的项目是前后端同时进行的,后端我已经有了完备的权限管理,前端不能的角色会有不同的访问数据权限.而在vue前后端分离开发情况下, ...

  3. C 数组、枚举类型enum

    传递数组给函数 告诉编译器函数要接受一个指针 skip //函数声明,数组的长度无需声明,因为编译器不会对形式参数进行边界检查 void myFunction(int param[]) //或者 vo ...

  4. NBIOT实现UDP协议的发送和接收(包含软件升级)

    源码下载: nbiot_module程序(java netbean) -> 提取码 UdpServer程序(C# vs2010) -> 提取码 QQ:505645074 前提条件:开NB卡 ...

  5. Google Analytics 学习笔记一 —— GA简介

    GA的原理 网页页面添加GA跟踪代码,以"一像素"传递信息给服务器 hit(交互) --> sessions(会话) --> user(用户) 竞品对比 Firebas ...

  6. 3.InfluxDB-InfluxQL基础语法教程--数据说明

    下面是本次演示的示例数据 表名:h2o_feet 数据示例: 数据描述 : 表h2o_feet中所存储的是6分钟时间区间内的数据. 该表有一个tag,即location,该tag有两个值,分别为coy ...

  7. Centos7安装和配置Tomcat8

    第一步:下载Tomcat8压缩包 进入 http://tomcat.apache.org/download-80.cgi 下载tar.gz压缩包 第二步:用xshell工具把压缩包上传到/home/d ...

  8. Microsoft Surface 2019新品发布会汇总

    Microsoft Surface 2019 新品发布会汇总 10月2日晚,微软举行了Microsoft Surface 2019秋季新品发布会,本次发布会涉及如下设备内容等: SurfaceLapt ...

  9. 关于Apache本地能访问外网不能访问的问题

    title: 关于Apache本地能访问外网不能访问的问题 date: 2018-08-05 19:22:12 tags: web --- 在配置apache和tomcat时,把它们都配置好,放到服务 ...

  10. 洛谷 P1182 数列分段 Section II

    洛谷 P1182 数列分段 Section II 洛谷传送门 题目描述 对于给定的一个长度为N的正整数数列A-iA−i,现要将其分成M(M≤N)M(M≤N)段,并要求每段连续,且每段和的最大值最小. ...