Symfony: сущность с гибкими отношениями и ее (под) формами - как проектировать?

1

У меня есть User -Entity с самой базовой информацией. User должен иметь возможность делиться более подробными данными в профиле. Для разных User существуют разные ProfileSet.

В этом примере я стараюсь, чтобы это было просто: ProfileSet_A - это профиль с личной информацией, ProfileSet_B хранит анонимные данные.

User может иметь только один ProfileSet.

Объекты (псевдокод)

// table: users
class User {
    protected $id,
              $email, 
              $username, 
              $password; // ...
}

// table: - none - 
class ProfileSet {
    protected $id,
              $name; // ...
}

// table: profileset_a
class ProfileSet_A extends ProfileSet {
    protected $firstname,
              $lastname,
              $morePrivateStuff; // ...
}

// table: profileset_b
class ProfileSet_B extends ProfileSet {
    protected $anyAnonymousStuff; // ...
}

// table: user_has_profileset
class UserHasProfileSet {
    protected $user,       // relation to User
              $profileSet; // relation to ProfileSet_A OR ProfileSet_B
}

Форма, ProfileSet_A

username:            [ textfield ]
email:               [ textfield ]
firstname:           [ textfield ]
lastname:            [ textfield ]
morePrivateStuff:    [ textfield ]

Форма, ProfileSet_B

username:            [ textfield ]
email:               [ textfield ]
anyAnonymousStuff:   [ textfield ]

Проблемы

  1. UserHasProfileSet должен относиться к User $user и ProfileSet, который может быть экземпляром ProfileSet_A или ProfileSet_B. Я хотел бы иметь только поле $profileSet вместо $profileSet_A, $profileSet_B ,...

  2. Я хотел бы отредактировать User и его ProfileSet (A или B) в той же форме.

Вопрос

Как решить проблемы чистым способом? Я открыт для лучших альтернатив. Может, я ошибаюсь.

Заранее спасибо!

Теги:
database
oop
symfony-forms

1 ответ

1
Лучший ответ

Если вы используете Doctrine в своем проекте, вы можете архивировать это с наследованием Doctrine, например с MappedSuperClass:

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="users")
 */
class User
{
    // other fields

    /**
     * @ORM\OneToOne(targetEntity="ProfileSet")
     */
    private $profile;
}

/**
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap({"a" = "ProfileSet_A", "b" = "ProfileSet_B"})
 * @ORM\Table(name="profile_sets")
 */
class ProfileSet
{
    // common properties
}

/**
 * @ORM\Entity
 * @ORM\Table(name="profile_sets_a")
 */
class ProfileSetA extends ProfileSet
{
    // ...
}

/**
 * @ORM\Entity
 * @ORM\Table(name="profile_sets_b")
 */
class ProfileSetB extends ProfileSet
{
    // ...
}

В этом случае Doctrine создаст 3 таблицы: profile_sets которые будут содержать общие поля, а тип профиля, profile_sets_a и profile_sets_b будут содержать определенные поля. Когда вы получаете Свойство User с $profile, Doctrine автоматически сопоставляет необходимый объект.

Поскольку у вас есть только одна запись ProfileSet для каждого User нет необходимости определять дополнительный UserHasProfileSet и вы можете просто установить связь OneToOne напрямую. Но вы можете сделать это так же, как вам нужно.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню