考虑以下场景:
在我的Laravel应用程序中有两个实体,如下所示:
Post
Page
Image
Video
以上所有实体都可以有CustomFieldValues,这是另一个实体。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        |

如您所见,CustomFieldDefinitions是额外数据的定义,我们可以存储每种类型的实体。
以下是来自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:1CustomFieldDefinition:1及其实体1的值(Post:1,在本例中,因为CustomFieldDefinition:1Post相关)是“https://twitter.com/StackOverflow”。
CustomFieldValue:2CustomFieldDefinition:2及其实体1的值(Page:1,在本例中,因为CustomFieldDefinition:2Page相关)是“我的页面的SEO标题”。
CustomFieldValue:3CustomFieldDefinition:3及其实体1的值(Image:1,在本例中,因为CustomFieldDefinition:3Image相关)是“http://example.com/image.jpg”。
CustomFieldValue:4CustomFieldDefinition:4及其实体1的值(Video:1,在本例中,因为CustomFieldDefinition:4Video相关)是“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相关的Posts,但是,不可能对关系执行如下操作:
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;
}

09-20 04:03