考虑以下场景:
在我的Laravel应用程序中有两个实体,如下所示:Post
Page
Image
Video
以上所有实体都可以有CustomFieldValue
s,这是另一个实体。custom_field_values
表的结构如下:
身份证件
实体id
自定义字段定义id
价值
[时间戳字段]
所有的CustomFieldValue
都属于一个CustomFieldDefinition
实体。其表custom_field_definitions
如下所示:
身份证件
父实体名称
定义名称
[时间戳字段]
以下是custom_field_definitions
表中的一些示例数据:
| ID | parent_entity_name | definition_name |
|----|--------------------|-------------------|
| 1 | Post | AuthorTwitterUrl |
| 2 | Page | SeoTitle |
| 3 | Image | OriginalSourceUrl |
| 4 | Video | MpaaRating |
如您所见,
CustomFieldDefinition
s是额外数据的定义,我们可以存储每种类型的实体。以下是来自
custom_field_values
表的一些sampel数据:| ID | entity_id | custom_field_definition_id | value |
|----|-----------|----------------------------|-----------------------------------|
| 1 | 1 | 1 | https://twitter.com/StackOverflow |
| 2 | 1 | 2 | My Page's SEO Title |
| 3 | 1 | 3 | http://example.com/image.jpg |
| 4 | 1 | 4 | G – General Audiences |
关于
custom_field_values
表中包含的数据的一点描述:CustomFieldValue:1
:CustomFieldDefinition:1
及其实体1的值(Post:1
,在本例中,因为CustomFieldDefinition:1
与Post
相关)是“https://twitter.com/StackOverflow”。CustomFieldValue:2
:CustomFieldDefinition:2
及其实体1的值(Page:1
,在本例中,因为CustomFieldDefinition:2
与Page
相关)是“我的页面的SEO标题”。CustomFieldValue:3
:CustomFieldDefinition:3
及其实体1的值(Image:1
,在本例中,因为CustomFieldDefinition:3
与Image
相关)是“http://example.com/image.jpg”。CustomFieldValue:4
:CustomFieldDefinition:4
及其实体1的值(Video:1
,在本例中,因为CustomFieldDefinition:4
与Video
相关)是“G–一般受众”。custom_field_values
表的entity_id
可以引用任何实体类,因此它不是DB级别的外键。只有结合custom_field_definition_id
我们才能找到它实际上指的是哪个实体。现在,一切都很好,直到我需要向任何实体添加一个名为
customFieldDefinitions
的关系(比如Post
)。class Post extends Model {
public function customFieldDefinitions(){
$this -> hasMany ('CustomFieldDefinition');
}
}
上述操作不起作用,因为指示
CustomFieldDefinition
关系的数据点不是custom_field_definitions
表中名为post_id
的外键字段。我们必须根据custom_field_definitions
表中的某些记录将“Post”作为字段parent_entity_name
的值,以某种方式建立关系。CustomFieldDefinition::where('parent_entity_name', '=', 'Post');
上面的片段获取与
CustomFieldDefinition
相关的Post
s,但是,不可能对关系执行如下操作:class Post extends Model {
public function customFieldDefinitions(){
$this
-> hasMany ('CustomFieldDefinition')
-> where ('parent_entity_name', '=', 'Post')
;
}
}
where
约束起作用。但Laravel也将当前Post
对象的ID注入到约束集中。所以,我想做的是,完全不考虑当前对象的ID,建立一个“类-叶关系”,而不是“对象级关系”。
在拉勒维尔的领导下这有可能吗?
最佳答案
可能有办法,但我不太确定。
您可以尝试定义一个变异的属性并将其设置为关系的本地键:
class Post extends Model
{
public function getEntityNameAttribute()
{
return 'Post';
}
public function customFieldDefinitions()
{
return $this->hasMany(
'CustomFieldDefinition',
'parent_entity_name',
'entity_name'
);
}
}
您还可以进一步定义一个特性,它可以被所有
customFieldDefinitions
的模型使用。可能看起来像:trait HasCustomFieldDefinitionsTrait
{
public function getEntityNameAttribute()
{
return (new ReflectionClass($this))->getShortName();
}
public function customFieldDefinitions()
{
return $this->hasMany(
'CustomFieldDefinition',
'parent_entity_name',
'entity_name'
);
}
}
然后你可以在任何需要的地方使用它:
class Post extends Model
{
use HasCustomFieldDefinitionsTrait;
}
class Video extends Model
{
use HasCustomFieldDefinitionsTrait;
}
class Page extends Model
{
use HasCustomFieldDefinitionsTrait;
}
class Image extends Model
{
use HasCustomFieldDefinitionsTrait;
}