Contracts

Laravel 的契约是一组定义框架提供的核心服务的接口, 例如我们在介绍用户认证的章节中到的用户看守器契约IllumninateContractsAuthGuard 和用户提供器契约IlluminateContractsAuthUserProvider以及框架自带的App\User模型所实现的IlluminateContractsAuthAuthenticatable契约。

为什么使用契约

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

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

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

定义和使用契约

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

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.

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

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

interface OrderRepositoryInterface 
{
 public function userOrders(User $user);
}
class OrderRepository implements OrderRepositoryInterface
{
 public function userOrders(User $user)
 {
  Order::where('user_id', '=', $user->id)->get();
 }
} 

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

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

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

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层了,将来切换存储实现也会很容易。

接口与团队开发

当你的团队在开发大型应用时,不同的部分有着不同的开发速度。

比如一个开发人员在开发数据层,另一个开发人员在做控制器层。

写控制器的开发者想测试他的控制器,不过数据层开发较慢没法同步测试。那如果两个开发者能先以interface的方式达成协议,后台开发的各种类都遵循这种协议。

一旦建立了约定,就算约定还没实现,开发者也可以为这接口写个“假”实现

class DummyOrderRepository implements OrderRepositoryInterface 
{
 public function userOrders(User $user)
 {
  return collect(['Order 1', 'Order 2', 'Order 3']);
 }
} 

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

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

然后这个应用的视图就可以用假数据填充了。接下来一旦后台开发者写完了真正的实现代码,比如叫RedisOrderRepository。

那么使用IoC容器切换接口实现,应用就可以轻易地切换到真正的实现上,整个应用就会使用从Redis读出来的数据了。

接口与测试

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

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']);
 } 

总结

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

到此这篇关于解析Laravel框架下的Contracts契约的文章就介绍到这了,更多相关laravel contracts契约 内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Laravel框架下的Contracts契约详解的更多相关文章

  1. Laravel自动生成UUID,从建表到使用详解

    今天小编就为大家分享一篇Laravel自动生成UUID,从建表到使用详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  2. laravel框架模型中非静态方法也能静态调用的原理分析

    这篇文章主要介绍了laravel框架模型中非静态方法也能静态调用的原理,结合实例形式分析了laravel模型基类中使用魔术方法实现非静态方法进行静态调用的相关原理,需要的朋友可以参考下

  3. Laravel相关的一些故障解决

    这篇文章主要给大家介绍了关于Laravel相关的一些故障的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者使用Laravel具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

  4. Laravel框架中缓存的使用方法分析

    这篇文章主要介绍了Laravel框架中缓存的使用方法,结合具体实例形式分析了Laravel框架中缓存的常用方法、操作步骤及相关使用操作技巧,需要的朋友可以参考下

  5. laravel 实现设置时区的简单方法

    今天小编就为大家分享一篇laravel 实现设置时区的简单方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  6. laravel框架学习记录之表单操作详解

    这篇文章主要介绍了laravel框架学习记录之表单操作,结合实例形式详细分析了laravel框架表单操作相关的路由请求、视图、资源、渲染、表单验证、错误记录等实现方法与操作注意事项,需要的朋友可以参考下

  7. Laravel框架基础语法与知识点整理【模板变量、输出、include引入子视图等】

    这篇文章主要介绍了Laravel框架基础语法与知识点整理,包括模板变量、输出、include引入子视图等相关操作技巧,需要的朋友可以参考下

  8. Laravel使用支付宝进行支付的示例代码

    本篇文章主要介绍了Laravel使用支付宝进行支付的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  9. Laravel开启跨域请求的方法

    今天小编就为大家分享一篇Laravel开启跨域请求的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  10. Laravel 重写日志,让日志更优雅

    这篇文章主要介绍了Laravel 重写日志,让日志更优雅,laravel框架俗称优雅的框架,所以有想对laravel中的日志重写使其更加方便的记录信息获取信息的同学可以参考下

随机推荐

  1. PHP个人网站架设连环讲(一)

    先下一个OmnihttpdProffesinalV2.06,装上就有PHP4beta3可以用了。PHP4给我们带来一个简单的方法,就是使用SESSION(会话)级变量。但是如果不是PHP4又该怎么办?我们可以假设某人在15分钟以内对你的网页的请求都不属于一个新的人次,这样你可以做个计数的过程存在INC里,在每一个页面引用,访客第一次进入时将访问时间送到cookie里。以后每个页面被访问时都检查cookie上次访问时间值。

  2. PHP函数学习之PHP函数点评

    PHP函数使用说明,应用举例,精简点评,希望对您学习php有所帮助

  3. ecshop2.7.3 在php5.4下的各种错误问题处理

    将方法内的函数,分拆为2个部分。这个和gd库没有一点关系,是ecshop程序的问题。会出现这种问题,不外乎就是当前会员的session或者程序对cookie的处理存在漏洞。进过本地测试,includes\modules\integrates\ecshop.php这个整合自身会员的类中没有重写integrate.php中的check_cookie()方法导致,验证cookie时返回的username为空,丢失了登录状态,在ecshop.php中重写了此方法就可以了。把他加到ecshop.php的最后面去就可

  4. NT IIS下用ODBC连接数据库

    $connection=intodbc_connect建立数据库连接,$query_string="查询记录的条件"如:$query_string="select*fromtable"用$cur=intodbc_exec检索数据库,将记录集放入$cur变量中。再用while{$var1=odbc_result;$var2=odbc_result;...}读取odbc_exec()返回的数据集$cur。最后是odbc_close关闭数据库的连接。odbc_result()函数是取当前记录的指定字段值。

  5. PHP使用JpGraph绘制折线图操作示例【附源码下载】

    这篇文章主要介绍了PHP使用JpGraph绘制折线图操作,结合实例形式分析了php使用JpGraph的相关操作技巧与注意事项,并附带源码供读者下载参考,需要的朋友可以参考下

  6. zen_cart实现支付前生成订单的方法

    这篇文章主要介绍了zen_cart实现支付前生成订单的方法,结合实例形式详细分析了zen_cart支付前生成订单的具体步骤与相关实现技巧,需要的朋友可以参考下

  7. Thinkphp5框架实现获取数据库数据到视图的方法

    这篇文章主要介绍了Thinkphp5框架实现获取数据库数据到视图的方法,涉及thinkPHP5数据库配置、读取、模型操作及视图调用相关操作技巧,需要的朋友可以参考下

  8. PHP+jquery+CSS制作头像登录窗(仿QQ登陆)

    本篇文章介绍了PHP结合jQ和CSS制作头像登录窗(仿QQ登陆),实现了类似QQ的登陆界面,很有参考价值,有需要的朋友可以了解一下。

  9. 基于win2003虚拟机中apache服务器的访问

    下面小编就为大家带来一篇基于win2003虚拟机中apache服务器的访问。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  10. Yii2中组件的注册与创建方法

    这篇文章主要介绍了Yii2之组件的注册与创建的实现方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下

返回
顶部