Архитектура Приложения, В Котором Используется Несколько Типов Пользователей

Возможно название темы не очень говорящее, не пришло в голову ничего лучше.

Небольшое предисловие.

Пишу веб-приложение для компании, которая предлагает услуги по созданию медиаконтента - смесь системы документооборота и приложения для работы с клиентами и их заказами.

Есть несколько типов пользователей: админ, менеджеры, клиенты, агентства и исполнители.

Админы имеют полный контроль над системой, могут создавать любых пользователей.

Менеджеры - то же что и админы только с ограничениями.

Клиенты могут работать только с заказами и документами, которые относятся к их заказам.

Клиентов могут вести агентства (клиенты "принадлежат" агентствам), т.е. агентства могут работать с заказами своих клиентов.

Исполнители непосредственно выполняют заказы, которые дают им менеджеры.

У каждого типа пользователя могут быть свои "атрибуты" и связанные модели, например, к исполнителю можно прицепить паспортные данные, контакты (аська, скайп), есть таблица платежей, которые поступают от менеджера или админа.

У клиента есть реквизиты, название компании и тоже таблица платежей, но уже менеджеру.

У всех пользователей есть общие поля - это почта, логин, пароль и имя.

Суть проблемы вот в чем:

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

У каждого типа пользователя есть своя панель управления, причем по функцианалу они весьма различные.

Пользователи должны иметь одну точку входа в панель, т.е. все пользователи заходят с одной страницы.

Есть такой вариант решения проблемы:

Создать одну модель (таблицу) пользователей с общими полями и полем "роль".

Создать несколько связанных таблиц, например, developer_payments, client_payments, developer_info, client_info и т.д.

По полю роль отслеживать тип пользователя и джойнить соответствующие таблицы.

Решение топорное, но работающее. В итоге получается много таблиц с префиксом developer_ или client_.

При этом когда нужно добавить новый тип пользователей приходится плодить таблицы.

Возможно есть более подходящее решение?

Нужна общая модель, которая включает атрибуты (поля, идентификаторы) присутствия доступа к возможности оплаты, внесения информации и т.д.

то есть создаются общие таблицы payments, info и существуют в качестве отношения many-to-many связные таблички между user и этими таблицами (user_payments, user_info)

Рассмотрим 2е таблицы developer_info (в ней такие поля: номер договора подряда, телефон, скайп, паспортные данные, дата рождения) и client_info (поля: название компании, имя, должность, рабочий телефон, мобильный телефон, номер основного договора, реквизиты). Если из этих 2х таблиц сделать одну user_info, то она будет содержать поля 2х таблиц, причем для клиентов будет заполняться одна часть таблицы, а для исполнителей другая. Если сюда добавить информацию о менеджерах и агентствах, то получится каша.

в любой каше есть основные компоненты, специфические компоненты либо обобщают, либо выделяют в отдельные таблицы, если они так важны

это как в ООП - нужно найти общее выделить в класс (таблицу), специфическое вынести за пределы класса через наследование и т.п. (в другую таблицу)

теоретически (ни в коем случае на практике) поля в таблицах вообще могут иметь общую форму, главное иметь возможность где-то общих, где-то разных методов работы с этими полями, например:

developer_info (в ней такие поля: номер договора подряда, телефон, скайп, паспортные данные, дата рождения)

client_info (поля: название компании, имя, должность, рабочий телефон, мобильный телефон, номер основного договора, реквизиты)

общие: имя (название), телефон(любой), номер договора, контакты(скайп, адрес, icq, email), реквизиты(паспортные данные), если они в одном общем текстовом поле

в итоге остается частное: дата рождения, должность (хотя они теоретически могут быть и у тех и у других)

другой подход: создаем таблицу персон, которая содержит все соответствующие поля для персоны-человека (имя, телефоны, паспорт, скайп, почта, адрес)

создаем таблицу компаний, которая которая содержит все соответствующие поля для компании (название, телефоны, реквизиты, адреса и прочее)

developer, админ, менеджер ссылаются на персоны

клиент, исполнитель ссылаются на компании и персоны

дальше в том же духе

Я бы сделал так:

  1. Таблица пользователей - id,username,email,password,role

  2. Таблицы для каждого типа пользователя {$role}_user, которая подключается для каждой модели разная.


Developer extends User {

    public function relations()

    {

        return array('info' => array(self::BELONGS_TO, 'DeveloperInfo', 'user_id'));

    }

}

Client extends User{

    public function relations()

    {

        return array('info' => array(self::BELONGS_TO, 'ClientInfo', 'user_id'));

    }

}

  1. Таблица платежей общая, many-to-many, плодить её не нужно если структура платежа не меняется в зависимости от типа пользователя. Так же можно будет поступить и с остальными таблицами user-to-user.

Не понял почему придётся плодить таблицы с префиксами. Достаточно ведь сделать client_info, developer_info - на каждый тип пользователя таблица.

а чем оно отличается от этого?:

Тем, что смысла плодить таблицы нет

конечно смысла нет, но если заводим новый тип пользователя, то по вашей схеме тоже придеться плодить :)