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 ]
问题
UserHasProfileSet
应该与 User $user
和 ProfileSet
相关,后者可能是 ProfileSet_A
或 ProfileSet_B
的实例。我只想使用字段 $profileSet
而不是 $profileSet_A
、$profileSet_B
、...
我想在同一表格中编辑 User
和 ProfileSet
(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_a
和 profile_sets_b
将包含特定字段。当您使用 $profile
属性 获取 User
时,Doctrine 将自动映射所需的对象。
由于每个 User
只有一个 ProfileSet
条目,因此没有必要定义额外的 UserHasProfileSet
实体,您可以直接设置 OneToOne
关联。但如果必须的话,你也可以这样做。
我有一个具有非常基本信息的 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 ]
问题
UserHasProfileSet
应该与User $user
和ProfileSet
相关,后者可能是ProfileSet_A
或ProfileSet_B
的实例。我只想使用字段$profileSet
而不是$profileSet_A
、$profileSet_B
、...我想在同一表格中编辑
User
和ProfileSet
(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_a
和 profile_sets_b
将包含特定字段。当您使用 $profile
属性 获取 User
时,Doctrine 将自动映射所需的对象。
由于每个 User
只有一个 ProfileSet
条目,因此没有必要定义额外的 UserHasProfileSet
实体,您可以直接设置 OneToOne
关联。但如果必须的话,你也可以这样做。