如何存储有关表的元数据?

Sep*_*ram 5 php mysql metadata

我有一张桌子.一个包含25列的大表,每列包含有关特定实体的原子数据.具体而言,实体是待售的房地产(如房间和房屋),因此该表称为财产.

每个属性都有一个子类(实际上这就是所谓的"类型",但我们会称之为"继承",以避免与数据类型的混乱),在这个时刻"已经建成,待出售"或"正在建设中,但可以投入".它还有很多属性,如地址,价格等,其中大部分都是在子类之间共享,但有些则不是.属性具有不同的数据类型,它们是:

  • 整数
  • 浮点数字
  • 短文本
  • 长长的文字
  • 其他表的外键

这些"其他表格"用于从主持人可编辑的选项列表中进行选择(例如城区列表,建筑公司列表等).

主持人应该能够创建新属性并进行编辑.用户应该能够查看某些属性的详细信息并搜索满足特定条件的属性,然后将其作为表格查看,可以按其中一列进行排序.

根据属性的子类,只有一部分属性属性可供用户查看,也可供主持人进行编辑.此外,根据数据类型,需要使用不同的HTML代码向用户显示这些属性,并为主持人提供编辑控件,以及在编辑后应执行不同的数据验证检查.

字段列表不是动态的 - 列的列表以及它们的显示方式不太可能经常更改,并且主持人无需更改它.

但是,由于25是一个相当大的数字,我想在一个地方组织并保存有关属性表的所有元数据:有关哪些子类是列的信息以及如何显示,编辑和验证数据.能够以一种简单的方式(如数组)从我的代码中访问所有这些元数据会很高兴.我看到三个选项:


1.常量PHP数组

只需创建一个PHP文件或函数,它将使用元数据构造数组,然后在需要时包含/调用它.

优点:

  • 简单.
  • 快速.

缺点:

  • 由于过于冗长和丑陋的PHP代码,难以维护.

2. MySQL数据库

在数据库中创建表property_meta并在其中存储元数据.新的表将包含列名从属性表中,数据的相关性在此列中的每个的特性的子类,预期的数据类型等等.然后创建将查询必要的字段以及作为数组返回得到的数据的功能.

优点:

  • 更容易更改元数据.
  • 维护的代码更少.
  • 可以在以后扩展到允许用户更改列的列表.从属性表中添加或删除列不会有太大问题.虽然在我看来,用户能够动态更改数据库架构是一个严重的代码味道.如我错了请纠正我.

缺点:

  • 每当更改元数据时,必须相应地更新服务器数据库.但它只会在数据库架构发生变化时发生,所以没有人关心.
  • 更慢 - 以创建阵列为代价,这将增加与服务器通信的成本和从数据库中选择数据的成本.虽然后者很可能被MySQL查询缓存机制否定.

3.将属性及其属性分隔到不同的表中

按照上面的解决方案创建元数据表,只将其命名为property_attribute.还可以使用propertyproperty_attribute的外键创建property_data表,并为属性值创建另一列.然后,属性表将只包含主键和子类,并且只能使用具有两个连接的查询来检索实际属性值.

优点:

  • 最灵活的解决方案 如果更改了属性列表,则数据库架构将保持不变.

缺点:

  • 每个property_data行将包含一段未知类型的数据.将它们全部存储为TEXT或BLOB,或者为单独的数据类型创建单独的列.两种解决方案看起来都很丑
  • 目前还不清楚如何从属性表中处理以前的外键.在每个插入上完成的自动数据完整性检查几乎不可能(可能使用触发器?我不确定).
  • 选择数据将变得更加困难.这些数据将被检取为property_id- property_attribute_id- valuetrinities,这是不直观,需要更多的努力才能正常输出.
  • 更重要的是,按一个或多个属性进行过滤和排序会将我带到受伤的世界.
  • 非常非常慢.
  • 感觉就像用直升机过马路一样.

坦率地说,我不喜欢这两种解决方案.但在我看来,第二个是最不丑的.你怎么看?

sim*_*aun 3

我向您提出的第一个问题是:您是否正在寻求帮助设计正确的数据库模式,或者您是否正在询问如何在代码中处理这些属性/子类?

数据库架构

数据库模式不完全是我的强项,所以我将把它留给可能比我更了解的人。
我可能只是将每个字段作为单个属性表中自己的列,因为它很简单并且可以让您正确索引每个字段。正如您所说,不会经常添加新字段。

在 PHP 中处理它

在我看来,将这些字段视为元数据是错误的。每个子类都有自己的一组字段,这意味着从技术上讲它们都是不同类型的实体。

为了清楚起见,我保持简单,但以下是我要做的事情:

  1. 为每个属性类型创建一个 POPO(普通 ole' php 对象)。
    这些只是值对象,类似于您在 ORM 中可能找到的对象。与 Doctrine2 实体一样,它们不执行任何类型的持久性。

  2. 这就是我简化示例的地方。这绝对不符合 SRP,而且在我看来是糟糕的设计,但为了简洁起见,我这样写。

    创建一个工厂类,负责从数据库获取数据并将数据保存到数据库,实例化适当的 POPO 并相应地填充数据。

这就是全部内容了。这是一个迷你 ORM。如果你愿意的话,你实际上可以取消#2并使用适当的ORM......

关键是每个属性子类都有单独的对象。这是有利的,因为:

  • 由于每个属性类型都有自己的类,并具有自己的预定义属性集(以及 getter/setter),因此您无需担心填充或使用属于其他属性类型的数据。
  • 它提供了明显的区别,您可以使用它来呈现特定于每种属性类型的模板。(并不是说你以前不能这样做......我只是觉得这种方式更干净。)
  • 每个属性类型类都可以从基类继承,以容纳属性类型中常见的所有字段。