Symfony:具有灵活关系的实体及其(子)形式 - 如何设计?

Symfony: Entity with flexible relations and it's (sub-)forms - how to design?

我有一个具有非常基本信息的 User-实体。 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 $userProfileSet 相关,后者可能是 ProfileSet_AProfileSet_B 的实例。我只想使用字段 $profileSet 而不是 $profileSet_A$profileSet_B、...

  2. 我想在同一表格中编辑 UserProfileSet(A 或 B)。

问题

如何干净利落地解决问题?我愿意接受最佳实践替代方案。可能是我想错了。

提前致谢!

如果您在项目中使用 Doctrine,您可以使用 Doctrine inheritance 将其存档,例如 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_aprofile_sets_b 将包含特定字段。当您使用 $profile 属性 获取 User 时,Doctrine 将自动映射所需的对象。

由于每个 User 只有一个 ProfileSet 条目,因此没有必要定义额外的 UserHasProfileSet 实体,您可以直接设置 OneToOne 关联。但如果必须的话,你也可以这样做。