Задать вопрос

Как правильно реализовать архитектуру для связанных объектов с сервисом, коллекцией и репозиторием?

Добрый день.
Есть таблица в бд, в ней хранится сущность: Post.
Сама по себе эта сущность не используется, в зависимости от некоторых строк в таблице, создается дочерняя сущность News, Article и.т.д, у которых есть одинаковые методы, но могут быть дополнительные разные методы.
Хотелось бы реализовать все это с репозиториями и интерфейсами, чтобы можно было менять при необходимости

Набросал пример, чтобы было хоть немного понятно, чего я хочу:
interface PostContract
{
    public function getId();
    public function getTitle();
}

interface NewsContract extends PostContract
{
    public function getCountry();
}

interface ArticleContract extends PostContract
{
    public function getTags();
}

abstract class Post implements PostContract
{
    public function getId()
    {
    }

    public function getTitle()
    {
    }
}

class News extends Post implements NewsContract
{
    public function getCountry()
    {
    }
}

class Article extends Post implements ArticleContract
{
    public function getTags()
    {
    }
}

interface NewsCollectionContract
{
    public function push(NewsContract $item);
}

interface ArticleCollectionContract
{
    public function push(ArticleContract $item);
}

class NewsCollection implements NewsCollectionContract
{
    public function push(PostContract $item)
    {
    }
}

class ArticleCollection implements ArticleCollectionContract
{
    public function push(ArticleContract $item)
    {
    }
}


interface PostRepositryContract
{
    public function getList();
}

interface NewsRepositryContract extends  PostRepositryContract
{
    public function getList() : NewsCollectionContract;
    public function get($id) : NewsContract;
}

interface ArticleRepositryContract extends  PostRepositryContract
{
    public function getList() : ArticleCollectionContract;
    public function get($id) : ArticleContract;
}

abstract class PostRepositry
{
    // Общие методы
}

class NewsRepository extends PostRepository implements NewsRepositryContract
{
    public function getList() : NewsCollectionContract
    {
        return new NewsCollection;
    }
    public function get($id) : NewsContract
    {
        return new News;
    }
}

class ArticleRepositry extends PostRepository implements PostRepositryContract
{
    public function getList() : ArticleCollectionContract
    {
        new ArticleCollection;
    }

    public function get($id) : ArticleContract
    {
        new Article;
    }
}

interface NewsServiceContract
{
    public function getList(array $params) : NewsCollectionContract;
}

interface ArticleServiceContract
{
    public function getList(array $params) : ArticleCollectionContract;
}

class NewsService implements NewsServiceContract
{
    private $repo;

    public function __construct(NewsRepositryContract $repo)
    {
        $this->repo = $repo;
    }

    public function getList(array $params) : NewsCollectionContract
    {
        return $this->repo->getList();
    }
}

class ArticleService implements ArticleServiceContract
{
    private $repo;

    public function __construct(ArticleRepositryContract $repo)
    {
        $this->repo = $repo;
    }

    public function getList(array $params) : ArticleCollectionContract
    {
        return $this->repo->getList();
    }
}


Как все это реализовать правильно?
  • Вопрос задан
  • 277 просмотров
Подписаться 6 Средний Комментировать
Помогут разобраться в теме Все курсы
  • Skillbox
    Веб-разработчик на PHP
    9 месяцев
    Далее
  • Хекслет
    PHP-разработчик
    10 месяцев
    Далее
  • Нетология
    Веб-разработчик с нуля: профессия с выбором специализации
    14 месяцев
    Далее
Решения вопроса 1
DeFacto
@DeFacto
глубоко ушел в абстракции.

1. Кто и для чего будет использовать методы getTags(), getCountry() ?

по логике допустим, у тебя интерфейс ArticleContract добавляет функции getTags()
лучше тогда создать интерфейс TagsContract
так как потом требования могут изменится, и тэги нужны будут для News

2. Зачем на каждый чих делать интерфейсы? Для Service я вообще не вижу смысла. Или ты собираешься подменять где-то ArticleService другим ArticelService который должен так же возвращать ArticleCollectionContract?

3. самый простой вариант для начала
оставляем interface PostContract
по-необходимости для функционала делаем interface TagContract
оставляем PostRepostory, PostService
PostRepostory расширяем чтобы он мог возвращать объекты по типу (например
$postRepostory->getNews(), $postRepostory->getArticles() )
В тех местах где тебе реально нужен доп функционал типа getCountry - создаешь отдельный интерфейс interface CountryContact
и далее в тех местах где будет зависимость встраиваешь CountryContact
в итоге class News extends Post implements CountryContact, TagContract
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
FoodSoul Калининград
от 180 000 до 250 000 ₽
IT-Spirit Москва
от 230 000 до 320 000 ₽
от 200 000 до 290 000 ₽