А как Вы избавляетесь от дублирования при решении типичных задач?

Доброго времени суток.
Задача: сделать каталоги фильмов, игр и знаменитостей на Yii2, все они имеют много общего (вывод списка, детальный вывод, фильтрация...).

Решение: написать базовый модуль Catalog и на его основе сделать модули Films, Games, Stars...
Для удобства опустим подробности реализации. Этот модуль реализует базовый функционал, который легко настроить и доработать с помощью переопределения.

Как вы решаете такие проблемы? Не писать же каждый раз одно и тоже. Например битрикс сделал инфоблоки, достаточно удобное и гибкое решение

Пример решения
/** Описание интерфейса базового модуля Каталог */
abstract class CatalogInterface
{
	/** @var bool Отображать фильтр */
	public $filter = false;

        abstract getModel();

	public function getListWidget()
	{
		return CatalogListWidget::classname();
	}
	
	public function getDetailWidget()
	{
		return CatalogDetailWidget::classname();
	}
	
	public function getFilterWidget()
	{
		return CatalogFilterWidget::classname();
	}
}

/** Базовый контроллер каталога */
abstract class CatalogController extends Controller
{
	/** @var CatalogInterface Класс описывающий интерфейс модуля */
	protected $interface = null;

	public function init()
	{
		$this->interface = Module::getInterface('catalog');
	}

	public function listAction()
	{
		if ($this->interface->filter)
		{
			$filterWidget = $this->interface->getFilterWidget();
			$filterWidget::widget();
		}

		$listWidget = $this->interface->getListWidget();
		$listWidget::widget();
	}

	public function detailsAction()
	{
		$detailsWidget = $this->interface->getDetailsWidget();

		$detailsWidget::widget();
	}
}

/** Конфигурация каталога в модуле Фильмы */
class FilmsCatalogInterface extends CatalogInterface
{
	/** @var bool Отображать фильтр */
	public $filter = true;
}

/** Контроллер каталога в модуле Фильмы */
class FilmsController extends CatalogController
{
	public function getModel()
        {
                 return Film::classname();
        }
}


Базовый модуль содержит базовый набор виджетов, готовые контроллеры и класс, в котором хранится конфигурация и неймспейсы используемых классов.
В итоге у нас есть возможность добавления и переопределения экшенов, замены и кастомизации виджетов.
Например мы можем на основе этого модуля создать модуль фильмов.
1. Опишем интерфейс как того требует модуль Каталог в классе FilmsCatalogInterface
2. Унаследуем контроллеры модуля Каталог
Всё, готово. Если нужно будет изменить детальный вывод фильма, мы можем переопределить виджет детального вывода, можно заменить шаблон или доработать его логику. В общем можно добавить больше возможностей для конфигурации и переопределения, это даст возможность изменить любой шаблон, контроллер и виджет.

На самом деле цель создать универсальное решение, которое позволило бы просто добавлять на сайт типичные разделы типа каталог фильмов, игр, книг, музыки с возможностью гибкой фильтрации... В целом они должны быть похожи, но при этом должна быть возможность создания других разделов, например каталог youtube-каналов.
В общем что-то на подобии инфоблоков битрикс и его компонентов
  • Вопрос задан
  • 326 просмотров
Пригласить эксперта
Ответы на вопрос 3
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
Решение: написать базовый модуль Catalog и на его основе сделать модули Films, Games, Stars...


ну без описания деталей решение мягко скажем... не полное. И ежу понятно что что бы устранить дублирование надо общие вещи вынести куда-то (базовый класс, общая зависимость). Другой вопрос - зачем в отдельные модули, но это может я не вкурсе специфики Yii2. В Symfony2 скажем многие при решении таких задач пихают все в отдельные бандлы и это не правильно, так как бандлы должны быть самодостаточными.

Как вы решаете такие проблемы?

Устраняем дублирование. Как - зависит от того где это дублирование проявляет себя. Если у нас много однотипных проверок (например в Yii1 был убогий ACL и я не думаю что что-то поменялось для Yii2) с проверкой ролей, можно вынести эти однотипные проверки в какой-то отдельный объект. Symfony и Spring предлагают подход с voter-ми (шаблон chain of responsibility)

Если речь идет о шаблонах - Twig предоставляет механизм наследования шаблонов, миксины и прочие чудные вещи которые позволяют устранить дублирование вообще полностью.

Если речь идет о банальном дублировании логики - эта логика выносится в отдельный объект. Это может быть как отдельня общая зависимость, либо базовый абстрактный класс (если принцип единой ответственности при этом мы не нарушаем).

Ну и да - логика может так же дублироваться для разных интерфейсов (http, cli, mq). В этом случае опять же "все общее выносится в общую зависимость". То есть логика переносится в сервисный слой.

Вариантов как устранить дублирование масса, но суть у всех вариантов одна - берем общее и выносим в общую зависимость.
Ответ написан
R0dger
@R0dger
Laravel/Yii/2 AngularJs PHP RESTful API
Ну если прямо вот одинаковые.. ну наследуйтесь от модели.. в которой все прописано и если надо переопределяйте методы.. но в большей части вывод, сохранение и чтение все равно чуть отличается...
Ответ написан
@strelov1
Похоже вам нужно подтянуть свои знания ООП в php прежде чем делать что-то на yii2
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы