Модель Entity-Attribute-Value с использованием codeigniter/php

ТАК Я пытаюсь создать способ структурировать мою базу данных, чтобы иметь возможность настраивать формы.

Я изучил шаблон 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, если это необходимо.


person Obaid    schedule 21.12.2010    source источник


Ответы (3)


Отказ от ответственности: я не знаком с PHP или CodeIgniter, но готов утверждать, что ни один из них не имеет какой-либо встроенной поддержки EAV. При этом я много знаю о EAV, поэтому отвечу в этом свете.

Когда вы пишете о поиске определенного значения, я предполагаю, что вы также имеете в виду конкретное поле. Итак, с учетом сказанного, поместите данные в XML CLOB вне таблицы форм (например, данные) и используйте функции MySQL MySQL для поиска по нему. Серьезно. Допустим, 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 = ?)

Все это выглядит хорошо и хорошо, теперь измените И на ИЛИ, и все вырвется на свободу.

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 = ?)

Вы видите проблему? INNER JOIN в предложении FROM означает, что записи будут возвращаться независимо от того, какие данные будут возвращены независимо от предложения WHERE. Таким образом, вместо JOIN в предложении FROM + WHERE, EAV требует EXISTS в предложении WHERE:

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 не очень хороши. Добавьте желание искать определенные типы данных, такие как даты и целые числа, и вы либо выполняете кастинг, либо работаете с несколькими столбцами в таблице form_field (например, field_date_value, field_int_value и т. д.).

Таким образом, XML CLOB означает только таблицу, которую следует учитывать при запросе, а также возможность использования многозначных атрибутов (на ум приходят множественные выборки или флажки).

person orangepips    schedule 02.01.2011

Из вашего вопроса похоже, что ваше требование состоит в том, чтобы получить идентификатор формы, когда у вас есть тип поля формы и значение поля -

Для этого вы можете попробовать следующий запрос:

Сначала запустите этот запрос, чтобы получить все идентификаторы форм с определенным типом поля =

    $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 у вас будет требуемый идентификатор формы.

мое предложение состоит в том, что вы используете enum для столбца field_type в таблице form_fields.

Надеюсь, что это помогает вам.

person Alpesh    schedule 29.12.2010

Прежде всего, поле form_id в вашей таблице form_data кажется избыточным. Каждая запись form_data ссылается на запись form_fields (через field_id), а каждая запись form_fields ссылается на запись формы (через form_id). Поэтому вам не нужно помещать form_id в таблицу form_data.

Ваши вопросы, кажется, таковы: как вы получаете значение form_id на основе определенного значения field_value?

Вот простой SQL-запрос, который должен помочь:

SELECT f.form_id FROM form_data d 
JOIN form_fields f USING(field_id) 
WHERE d.field_value = '??????'
person Burak Guzel    schedule 27.12.2010