使用codeigniter / php的实体属性值模型

时间:2010-12-21 19:59:59

标签: php mysql codeigniter entity-attribute-value

所以我试图创建一种方法来构建我的数据库,以便能够自定义表单。

我查看了EAV模式,这是我的数据库结构:

表格 - form_id - form_name - form_added_on - form_modified_at

表:form_fields - field_id - form_id - field_type(TEXT,RADIO等..) - field_default_value - field_required

表:form_data - data_id - field_id - form_id - field_value

所以现在我可以将任何自定义表单存储到数据库中,如果我想获取单个表单的值,我可以通过“form_id”简单地加入它。

问题:

我希望能够搜索特定字段值的所有表单。

我怎样才能使用EAV模型?

另外,我想过将自定义数据存储为序列化(JSON)对象,但后来我不确定如何查询该数据。

请注意我正在使用Codeigniter和MYSQL。因此,如果需要,会话可以使用Codeigniter库。

3 个答案:

答案 0 :(得分:3)

免责声明:我不知道PHP或CodeIgniter,但我愿意断言它既没有对EAV的任何内置支持。注意到,我知道关于EAV的很多所以我会在那个问题上回答。

当您撰写关于搜索特定值的文章时,我假设您在某个特定领域也有意思。因此,如上所述,将数据放在表单表格(例如数据)中的XML CLOB中,并使用MySQL's XML functions对其进行搜索。认真。假设XML看起来像:

<data>
    <field id="[field_id]">value</field>
</data>

按原样搜索:

SELECT f.form_id
FROM
  form f
WHERE 
  f.form_id = ?
  AND ExtractValue(data, '//field[@id="[field_id]"]') = ?

为什么呢?问题是针对EAV模型搜索多个标准具有挑战性。考虑这个例子:

SELECT f.form_id
FROM
  form f
    INNER JOIN form_fields f1 ON f1.form_id = f.form_id
    INNER JOIN form_fields f2 ON f2.form_id = f.form_id
WHERE 
  f.form_id = ?
  AND 
  (f1.field_id = ? AND f1.field_value = ?)
  AND 
  (f2.field_id = ? AND f2.field_value = ?)

这一切似乎都很好,现在将 AND 改为 OR ,所有地狱都破裂了。

SELECT f.form_id
FROM
  form f
    INNER JOIN form_fields f1 ON f1.form_id = f.form_id
    INNER JOIN form_fields f2 ON f2.form_id = f.form_id
WHERE 
  f.form_id = ?
  OR 
  (f1.field_id = ? AND f1.field_value = ?)
  OR 
  (f2.field_id = ? AND f2.field_value = ?)

你看到了这个问题吗? FROM子句中的INNER JOIN表示无论什么记录,无论WHERE子句如何都返回数据。因此,在FROM子句+ WHERE子句中不是JOIN,而是在WHERE中需要一个EXISTS:

SELECT f.form_id
FROM
  form f
WHERE 
  f.form_id = ?
  AND (
    EXISTS (
      SELECT f1.form_id FROM form_fields f1 
      WHERE f1.field_id = ? AND f1.field_value = ? AND f1.form_id = f.form_id
    )
    -- note OR search 
    EXISTS (
      SELECT f2.form_id FROM form_fields f2
      WHERE f2.field_id = ? AND f2.field_value = ? AND f2.form_id = f.form_id
    )
  )
有点难看啊?那和MySQL subquery performance is not good。添加搜索特定数据类型(例如日期和整数)的愿望,并且您要在form_field表中投射或使用多个列(例如field_date_value,field_int_value等...)。

因此,XML CLOB仅表示查询时要考虑的表以及多值属性的可能性(多选或复选框都会浮现在脑海中)。

答案 1 :(得分:1)

从您的问题看,您的要求是在获得表单字段类型和字段值时获取表单ID -

为实现此目的,您可以尝试以下查询 -

首先触发此查询以获取具有特定字段类型=

的所有表单ID
    $sql = "SELECT ff.form_id from form_fields ff where ff.field_type = 'The field type you are searching for'";

    $result = $this->db->query($sql);

    $form_ids = $result->result_array();

现在您可以在第二个查询中使用此数组来获取最终结果,如下所示 -

    $this->db->select('fd.form_id');
    $this->db->from('form_data fd');
    $this->db->where('fd.field_value','your field value');
    $this->db->where_in('fd.form_id',$form_ids);
    $required_form_id = $this->db->get();

因此,在变量$required_form_id中,您将获得所需的表单ID。

我的建议是你在form_fields表中使用enum作为field_type列。

希望这可以帮助你。

答案 2 :(得分:0)

首先,form_data表中的form_id字段似乎是多余的。每个form_data记录引用一个form_fields记录(通过field_id),每个form_fields记录引用一个表单记录(通过form_id)。所以你不需要将form_id放在form_data表中。

您的问题似乎是:如何根据特定的field_value获取form_id值?

这是一个简单的SQL查询,可以解决这个问题:

SELECT f.form_id FROM form_data d 
JOIN form_fields f USING(field_id) 
WHERE d.field_value = '??????'