【问题标题】:Dependency inversion issue in php. (Repository Pattern)php中的依赖倒置问题。 (存储库模式)
【发布时间】:2020-02-13 14:07:31
【问题描述】:

我在 Laravel 中实现一个仓库模式,看起来很乏味。例如,假设我有产品,然后我必须创建一个 ProductRepository 接口,然后是一个实现该接口的 ProductRepository 类,现在我在 ProductRepository 上有一些非常通用的方法,例如:

  • 全部检索
  • 商店
  • 更新
  • 删除

现在我必须对配料做同样的事情。如果我可以简单地使用所有这些泛型方法创建一个 ModelRepository 接口并通过传递一个类似于 Java 泛型的泛型数据类型(即模型)来实现它,那就太好了:

<?php
interface ModelRepositoryInterface<T> {
    function retrieveAll(): Collection<T>;
    function store(T $item);
    function update(int $id, T $data);
    function delete(int $id);
}

但是由于 php 不支持泛型,我该如何实现这种简单性呢?

【问题讨论】:

  • 这取决于数据产品/增量有什么,除了方法之外它们有什么共同点吗?
  • 我不相信他们拥有的数据是相关的,但产品应该有,例如名称、代码、单位成本......而成分应该有名称、测量单位和重新订购级别。
  • 你知道接口也可以“扩展”其他接口吗?
  • 是的,但这只会对 delete 方法有用,它不接受或输出特定模型。 @B001ᛦ
  • 也许可以看看“接口隔离”

标签: php laravel repository-pattern solid-principles dependency-inversion


【解决方案1】:

您可以创建一个 RepositoryServiceProvider 来将您的存储库接口绑定到实际的类。

您可以使用retrieveAll 创建一个抽象的Repository 类,存储、更新、删除和扩展您的Repositories 并实现该接口。如果我没有任何自定义,我在下面的示例中包含了魔术函数,以便能够雄辩地使用方法。

以下内容未经测试,只是为了了解一下。

<?php


namespace App\Repositories;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

abstract class AbstractRepository implements RepositoryInterface
{
    /**
     * @var Builder|Model
     */
    protected $model;
    /**
     * @return mixed
     */
    public function getModel()
    {
        return $this->model;
    }

    /**
     * @param array $columns
     * @return \Illuminate\Database\Eloquent\Collection|Model[]
     */
    public function all($columns = ['*'])
    {
        return $this->model->all($columns);
    }

    /**
     * @param $name
     * @param $arguments
     * @return mixed
     */
    public function __call($name, $arguments)
    {
        return $this->model->{$name}($arguments);
    }
}

订单仓库

<?php

namespace App\Repositories;

use App\Models\Order;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;

class OrderRepository extends AbstractRepository implements OrderRepositoryInterface
{
    /**
     * OrderRepository constructor.
     * @param Order $model
     */
    public function __construct(Order $model)
    {
        $this->model = $model;
    }

    public function countPaid(): int
    {
        return $this->model->paid()->count();
    }

    /**
     * @return int
     */
    public function countReady(): int
    {
        return $this->model->ready()->count();
    }

    /**
     * @return int
     */
    public function countCancelled(): int
    {
        return $this->model->cancelled()->count();
    }

}

OrderRepositoryInterface

<?php


namespace App\Repositories;


interface OrderRepositoryInterface
{

}

RepositoryServiceProvider

<?php

namespace App\Providers;

use App\Repositories\OrderRepository;
use App\Repositories\OrderRepositoryInterface;
use Illuminate\Support\ServiceProvider;

class RepositoryServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind(OrderRepositoryInterface::class, OrderRepository::class);
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

存储库接口

<?php


namespace App\Repositories;


use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;

interface RepositoryInterface
{
    function retrieveAll(): Collection;
    function store(Model $item);
    function update(int $id, Model $data);
    function delete(int $id);
}

【讨论】:

  • OrderRepository 在构造函数中接受模型,你将如何将它传递给控制器​​
  • 存储库已绑定且构造函数已具有模型类型。所以在你的控制器中你可以做到。公共函数显示(OrderRepositoryInterface $orderRepsitory){ $orders = $orderRepsitory->retrieveAll(); }
猜你喜欢
  • 2019-08-03
  • 1970-01-01
  • 1970-01-01
  • 2014-07-27
  • 1970-01-01
  • 1970-01-01
  • 2023-01-18
  • 1970-01-01
  • 2022-11-20
相关资源
最近更新 更多