我会尽量解释清楚这两个概念。
接口\合同
一般来说,OOP 接口用于描述实现该接口的类提供哪些方法/功能而不关心实际的实现。
Laravel 使用Contracts 主要是为了将服务 与实际实现分开。为了更清楚,让我们举个例子
<?php
namespace App\Orders;
class OrdersCache
{
protected $cache;
public function __construct(\SomePackage\Cache\Memcached $cache)
{
$this->cache = $cache;
}
public function find($id)
{
if ($this->cache->has($id)) {
//
}
}
}
正如您在此类中看到的,代码与缓存实现紧密耦合(即\SomePackage\Cache\Memcached),因此如果该缓存类的 API 发生更改,我们的代码也必须相应更改。如果我们想用另一个(例如redis)更改缓存实现,也会发生同样的事情。
我们的代码可能依赖于与实现无关的接口,而不是这样做:
<?php
namespace App\Orders;
use Illuminate\Contracts\Cache\Repository as Cache;
class OrdersCache
{
public function __construct(Cache $cache)
{
$this->cache = $cache;
}
public function find($id)
{
if ($this->cache->has($id)) {
//
}
}
}
现在我们的代码没有与任何特定的实现耦合,因为Cache 实际上是一个接口。所以基本上在我们的类中,我们需要一个类的实例表现 就像Cache 接口中描述的那样,但我们对它在内部的工作方式并不真正感兴趣。这样做,如果我们想更改缓存实现,我们可以编写一个实现接口Cache 的类,而无需更改OrdersCache 类中的任何代码行。这样做我们的代码更容易理解和维护,并且你的包更易于重用。有关更多示例,请参阅 Laravel 文档中的 Loose Coupling 部分。
接口和服务容器
Laravel 的主要功能之一是它的Service Container,它用于管理依赖和执行依赖注入。请查看 Laravel 文档中的 Service Container 定义。
依赖注入也被 Laravel 广泛用于将接口绑定到实现。举个例子吧:
$app->bind('App\Contracts\EventPusher', 'App\Services\RedisEventPusher');
让我们的班级成为
<?php
namespace App\Http\Controllers;
use App\Contracts\EventPusher;
class EventsController extends Controller
{
protected $pusher;
public function __construct(EventPusher $pusher)
{
$this->pusher = $pusher;
}
}
没有声明任何其他内容,我们基本上是在说每次有人需要 EventPusher 实例时,请 Laravel 提供 RedisEventPusher 类的实例。在这种情况下,每次实例化您的控制器时,Laravel 都会将 RedisEventPusher 的实例传递给您的控制器,而无需指定任何其他内容。
您可以通过查看 Laravel 文档中的 Binding Interfaces to Implementation 部分来深入了解。
存储库
存储库是适用于 MVC 模式的概念,独立于任何特定框架。通常,您的模型是 数据层(例如,直接与数据库交互),控制器处理 数据层 的访问逻辑,视图显示控制器提供的数据。
存储库可以定义如下:
简单来说,存储库模式是一种存储数据访问逻辑的容器。它从业务逻辑中隐藏了数据访问逻辑的细节。换句话说,我们允许业务逻辑在不了解底层数据访问架构的情况下访问数据对象。
Soruce:https://bosnadev.com/2015/03/07/using-repository-pattern-in-laravel-5
要了解如何在 Laravel 中使用它们,请查看great article。
就是这样,我希望它能帮助你理清思路。