Laravel中存储库和接口的用法是什么?

时间:2017-08-28 07:49:16

标签: php laravel laravel-5 interface repository

从2年开始使用Codeigniter开发了一些项目后,我开始学习Laravel。

我下载了一些项目,了解它们是如何编码的。据我所知,他们中的许多人只使用与Codeigniter相同的模型,视图和控制器。

但是有一个项目使用了存储库和接口。很难理解该项目的最新进展。那么Laravel中存储库和接口的用法是什么?我什么时候应该使用它们?

5 个答案:

答案 0 :(得分:18)

我将尽可能清楚地解释这两个概念。

<强>接口\合同

通常,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),因此如果该Cache类的API更改我们的代码,则必须相应地更改。如果我们想要用另一个更改Cache实现(例如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的一个主要功能是它的服务容器,它用于管理依赖项和执行依赖项注入。请查看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模式的概念。通常,您的模型是数据层(例如,直接与数据库交互),您的Controller处理数据层的访问逻辑和您的View显示财务主任提供的数据。

存储库可以定义如下:

  

简而言之,Repository模式是一种存储数据访问逻辑的容器。它隐藏了业务逻辑中数据访问逻辑的细节。换句话说,我们允许业务逻辑在不了解底层数据访问体系结构的情况下访问数据对象    Soruce https://bosnadev.com/2015/03/07/using-repository-pattern-in-laravel-5

要了解如何在Laravel中使用它们,请查看此great article

这就是全部,我希望有助于澄清你的想法。

答案 1 :(得分:9)

接口是任何实现类应该调用的。

interface CanFlyInterface
{
    public function fly();
}

把它想象成编程而不用打扰逻辑。

if ($object instanceof CanFlyInterface) {
    $obj->fly();
}

现在我们可以传递一个Bird对象或一个Airplane对象! PHP没有关注,只要它实现了接口!

class Bird implements CanFlyInterface
{
    public function fly()
    {
        return 'flap flap!';
    }
}

class Aeroplane implements CanFlyInterface
{
    public function fly()
    {
        return 'roar! whoosh!';
    }
}

你的另一个问题,Repository类是什么。它只是一个将所有数据库查询保存在一个位置的类。以此界面为例:

interface RepositoryInterface
{
    public function insert(array $data);
    public function update(array $data);
    public function findById($id);
    public function deleteById($id);
}

希望这应该为你解决问题!祝你好运PHP编码:-D

答案 2 :(得分:5)

首先,在更大的应用程序中使用Repository和Interface不仅是Laravel的受益者,也是编码标准和分离关注的所有技术的受益者。

根据Microsoft (我在此处找到了最佳解释)

为何使用存储库:

  

使用存储库分隔检索数据的逻辑   从作用于的业务逻辑将其映射到实体模型   模型。业务逻辑应该与数据类型无关   包括数据源层。存储库介于两者之间   数据源层和应用程序的业务层。它   查询数据的数据源,映射数据中的数据   源于业务实体,并持续改变业务   实体到数据源   存储库将业务逻辑分开   来自与底层数据源或Web服务的交互。   数据和业务层之间的分离有三个好处:   它集中了数据逻辑或Web服务访问逻辑。它提供   单元测试的替换点。它提供了灵活性   可以作为整体设计的结构   应用程序发展。存储库可以通过两种方式进行查询   商业实体。它可以向客户端提交查询对象   业务逻辑或它可以使用指定业务的方法   标准。在后一种情况下,存储库在上面形成查询   客户代表。存储库返回一组匹配的实体   满足查询。

对于Interface,你上面有很多答案,希望你能理解。

答案 3 :(得分:4)

让我们从更简单的界面开始:

您通常使用接口来实现具有所需方法的类: http://php.net/manual/en/language.oop5.interfaces.php

  

Laravel的Contracts是一组接口,用于定义框架提供的核心服务。例如,Illuminate \ Contracts \ Queue \ Queue合约定义了排队作业所需的方法,而Illuminate \ Contracts \ Mail \ Mailer合同定义了发送电子邮件所需的方法。   https://laravel.com/docs/5.4/contracts#introduction

当Laravel运行时,它可以检查一个类是否实现了一个特殊的接口:

if ($cls instanceof IInterface) {
    $cls->interfaceFunction();
}

由于Laravel能够使用队列,它将通过检查现有接口来检查事件是否应该排队。

  

要通知Laravel应广播给定事件,请在事件类上实现Illuminate \ Contracts \ Broadcasting \ ShouldBroadcast接口。   https://laravel.com/docs/5.4/broadcasting#defining-broadcast-events

<强>存储库:

我没有发现这么多:

  

我们的存储库不应该知道谁在为他们提供数据或者他们如何提供数据。 https://laravel.com/docs/5.4/contracts#loose-coupling

但我在网页上找到了其他一些信息:

  

存储库将工厂与网关连接   https://code.tutsplus.com/tutorials/the-repository-design-pattern--net-35804

该链接将为您提供有关详细信息的更多信息。

希望我能帮到你:)。

答案 4 :(得分:2)

首先,存储库和接口并非特定于Laravel,而是大多数语言中的通用编码标准。

如果你不介意花几美元,那么Laracasts下面的视频将有助于理解基础知识。

https://laracasts.com/lessons/repositories-and-inheritance

https://laracasts.com/series/object-oriented-bootcamp-in-php