Проблема инверсии зависимостей в php. (Шаблон репозитория) - PullRequest
0 голосов
/ 13 февраля 2020

Я реализую шаблон репозитория в Laravel, и он кажется очень утомительным. Например, скажем, у меня есть продукты, затем я должен создать интерфейс ProductRepository, а затем класс ProductRepository, который реализует этот интерфейс, теперь у меня есть несколько очень обобщенных c методов в ProductRepository, таких как:

  • retrieveAll
  • store
  • update
  • delete

И теперь я должен сделать то же самое для ингредиентов. Было бы хорошо, если бы я мог просто создать интерфейс ModelRepository со всеми этими обобщенными c методами и реализовать его, передав универсальный c тип данных (а именно модель), что-то похожее на Java Generics:

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

Но так как php не поддерживает дженерики, как мне достичь этой простоты?

1 Ответ

1 голос
/ 13 февраля 2020

Вы можете создать RepositoryServiceProvider для привязки ваших интерфейсов репозитория к реальным классам.

Вы можете создать абстрактный класс репозитория с помощью retrieveAll, хранить, обновлять, удалять и расширять свои репозитории и реализовывать интерфейс. Я включил ниже пример с функциями magi c, чтобы иметь возможность красноречивых методов, если у меня нет никакой настройки.

Ниже не проверено, но это просто, чтобы понять.

<?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);
    }
}

OrderRepository

<?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()
    {
        //
    }
}

RepositoryInterface

<?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);
}
...