D
D
Dmitry Baibukhtin2015-11-17 23:12:16
Yii
Dmitry Baibukhtin, 2015-11-17 23:12:16

And how do you get rid of duplication in solving typical problems?

Good day.
Task: make catalogs of movies, games and celebrities in Yii2, they all have a lot in common (listing, detailed output, filtering...).
Solution: write a basic Catalog module and make the Films, Games, Stars modules based on it...
For convenience, we will omit the implementation details. This module implements basic functionality that is easy to customize and modify using overrides.
How do you solve such problems? Don't write the same thing every time. For example, Bitrix made infoblocks, a fairly convenient and flexible solution
Example of a solution

/** Описание интерфейса базового модуля Каталог */
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();
        }
}

The base module contains a basic set of widgets, ready-made controllers and a class that stores the configuration and namespaces of the classes used.
As a result, we have the ability to add and redefine actions, replace and customize widgets.
For example, we can create a movie module based on this module.
1. Describe the interface as required by the Catalog module in the FilmsCatalogInterface class
2. Inherit the controllers of the Catalog module
Everything is ready. If we need to change the detailed output of the movie, we can redefine the detailed output widget, we can replace the template or modify its logic. In general, you can add more options for configuration and redefinition, this will make it possible to change any template, controller and widget.
In fact, the goal is to create a universal solution that would allow you to simply add typical sections to the site such as a catalog of movies, games, books, music with the possibility of flexible filtering ... In general, they should be similar, but it should be possible to create other sections, e.g. youtube channel directory.
In general, something similar to Bitrix infoblocks and its components

Answer the question

In order to leave comments, you need to log in

3 answer(s)
S
Sergey, 2015-11-18
Protko @Fesor

Solution: write a basic Catalog module and make Films, Games, Stars... modules based on it.

Well, without describing the details, the solution, to put it mildly, is not complete. And it’s a no brainer that in order to eliminate duplication, you need to move common things somewhere (base class, common dependency). Another question is why in separate modules, but I may not be aware of the specifics of Yii2. In Symfony2, for example, when solving such problems, many people shove everything into separate bundles, and this is not correct , since bundles should be self-sufficient .
Eliminate duplication. How - depends on where this duplication manifests itself. If we have a lot of checks of the same type (for example, in Yii1 there was a poor ACL and I don’t think that something has changed for Yii2) with checking roles, we can move these checks of the same type to some separate object. Symfony and Spring offer an approach with voters (chain of responsibility pattern)
When it comes to templates, Twig provides template inheritance, mixins and other wonderful things that allow you to eliminate duplication altogether.
If we are talking about a banal duplication of logic - this logic is taken out in a separate object. It can be either a separate shared dependency, or a base abstract class (if we do not violate the single responsibility principle).
Well, yes - the logic can also be duplicated for different interfaces (http, cli, mq). In this case, again, "everything that is common is taken out into a common dependence." That is, the logic is transferred to the service layer.
There are a lot of options on how to eliminate duplication, but the essence of all options is the same - we take the general and put it into a general dependence.

A
Andrew, 2015-11-18
@R0dger

Well, if they are exactly the same .. well, inherit from the model .. in which everything is written and, if necessary, override the methods .. but for the most part, output, saving and reading are still slightly different ...

E
Elios, 2015-11-18
@strelov1

Looks like you need to brush up your knowledge of OOP in php before doing anything in yii2

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question