Реализация репозитория + фабричного шаблона для классов с множественным наследованием в PHP? - PullRequest
0 голосов
/ 27 марта 2020

Вот случай: допустим, у меня есть User абстрактный класс. Этот класс расширен до Employee и Customer подклассов.

Класс User имеет атрибуты basi c, такие как name и address. Employee имеет дополнительный атрибут sallary. Customer имеет дополнительный атрибут membership_code.

Эти сущности хранятся в нескольких таблицах: users, employees и customers. Таблица users содержит основную c информацию о любом пользователе. Таблицы employees и customers относятся к таблице users, и в каждом из них содержатся дополнительные атрибуты.

users таблица:

id | name       | address           | type
---+------------+-------------------+---------
1  | Employee 1 | First Address St. | Employee
2  | Customer 1 | First Address St. | Customer

employees таблица:

user_id | salary
--------+---------
1       | 5000

customers таблица:

user_id | membership_code
--------+---------
2       | 1325_5523_2351

Вот что я имею в виду относительно того, как они должны быть реализованы в PHP:

abstract class User
{
    protected $id;
    protected $name;

    public static function load(int $id): User
    {
        /** @var array $data */
        $data = get_a_row_from_users_table_by($id); // this part does a query to DB

        return new $data['type']($data['id'], $data['name']);
    }

    final public function __construct($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
        $this->init();
    }

    abstract protected function init();
}

class Employee extends User
{
    protected $salary;

    protected function init()
    {
        /** @var array $data */
        $data = get_a_row_from_employees_table_by($this->id); // this part does a query to DB
        $this->salary = $data['salary'];
    }
}

class Customer extends User
{
    protected $membership_code;

    protected function init()
    {
        /** @var array $data */
        $data = get_a_row_from_customers_table_by($this->id); // this part does a query to DB
        $this->salary = $data['membership_code'];
    }
}

Вот как это будет выглядеть в контроллере:

$employee = User::load(1); // return Employee type
$customer= User::load(2); // return Customer type

Тем не менее, я чувствую, что приведенный выше код все еще кажется немного хакерским, чтобы его поддерживать. Недавно я прочитал книгу, в которой обсуждается доменный дизайн и как механизм персистентности следует разделить на репозиторий . С другой стороны, я также обнаружил, что механизм переключения типов, например между Employee и Customer, должен быть выполнен на Factory .

У меня есть немного gr asp к понятиям Repository и Factory , но я так и не смог понять, как объединить и реализовать эти понятия в работающий код.

В этом случае, как следует реализовать вышеизложенное для использования шаблона Repository и Factory в PHP?

1 Ответ

0 голосов
/ 28 марта 2020

Ваш подход к созданию User абстрактного базового класса хорош. Структура вашей таблицы также выглядит хорошо.

Имейте в виду, что ваши сущности (такие как User) не должны зависеть от инфраструктуры, потому что включение инфраструктуры в вашу сущность отталкивает вас от SRP. в приведенном выше примере ваша сущность User выполняет слишком много работы ... логика c для чтения и записи в БД должна быть извлечена из сущности ... они принадлежат UserRepository

Ваше предположение о помещении механизма персистентности в репозиторий верно. Вы можете реализовать generi c UserRepository, который возвращает Employee и Customer ... как вы хотите реализовать репозиторий generi c по вашему выбору, но независимо от этого, логика сохранения c не принадлежит User Сущность.

...