【问题标题】:Entity-attribute-value model using codeigniter / php使用codeigniter / php的实体-属性-值模型
【发布时间】:2010-12-21 19:59:58
【问题描述】:

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

我研究了 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 - 字段值

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

问题:

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

如何使用 EAV 模型做到这一点?

此外,我曾考虑将自定义数据存储为序列化 (JSON) 对象,但我不确定如何查询该数据。

请注意,我将 Codeigniter 与 MYSQL 一起使用。因此,如果对话可以在需要时使用 Codeigniter 库。

【问题讨论】:

    标签: php mysql codeigniter entity-attribute-value


    【解决方案1】:

    免责声明:我不知道 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 子句都返回数据。因此,EAV 要求在 WHERE 中使用 EXISTS,而不是在 FROM 子句 + WHERE 子句中加入 JOIN:

    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 意味着查询时只考虑表以及多值属性的可能性(想到多选或复选框)。

    【讨论】:

      【解决方案2】:

      从您的问题看来,您的要求是在具有表单字段类型和字段值时获取表单 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 表中对 field_type 列使用枚举。

      希望对你有所帮助。

      【讨论】:

        【解决方案3】:

        首先,您的 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 = '??????'
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-11-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多