Как сохранить изменения в дальнейшем?

Модераторы моего webapp имеют возможность изменять некоторые данные в базе данных. Эти изменения видны всем пользователям. Но по какой-то причине я не хочу, чтобы они применялись немедленно, а скорее только после определенного действия, например, когда я явно принимаю. Сроки:

  • Поле в таблице имеет значение PreviousValue.
  • Модератор запрашивает это значение как NewValue.
    Все пользователи продолжают видеть значение PreviousValue.
  • Я принимаю изменения.
    Теперь все пользователи видят значение NewValue.

Проблема в том, что модераторы могут изменять поля в большом количестве таблиц. Каков наилучший способ справиться с этими временными значениями? Я могу представить эти решения, но ни один из них не звучит хорошо:

  • Дублируйте все таблицы (вместе MyTable и MyTable_ToApply).
  • Добавьте специальную таблицу (ToApplyTable) с четырьмя полями: таблицу для изменения, поле для изменения, идентификатор записи для изменения и новое значение, которое необходимо применить.

Есть ли у вас лучшие идеи?

Ответы

Ответ 1

Как только вопрос будет довольно широким (и может иметь много хороших ответов) - это не ответ, а другое возможное решение:

у вас может быть таблица типа:

id - just autogenerated number
datetime - date of change
changed_by - string with name of actor or id of some user
oldvalue - just old value
newvalue - just new value
update_insert_sql - here you put actual SQL which should be executed (you already have this sql in your current code)
state - 0 - it is not applied to db, 1 - already executed, 2 - you're rejected this change
datetime_of_apply - just date of action
datetime_of_reject - just date of action

ПРИМЕЧАНИЕ. Вместо хранения старого значения вы можете сохранить SQL для получения текущего значения, это поможет вам, если несколько изменений от разных модераторов будут перенесены в одну строку/столбец

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

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

Ответ 2

Вот как работает Wordpress с этим материалом. Вы можете иметь в той же таблице опубликованное сообщение, а затем, в виде новых строк, коллекцию неопубликованных ревизий разных авторов, созданных в разное время, и, конечно, связанных с главным сообщением.

Обновление

Например, если вы используете доктрину, вам нужен только один и тот же репозиторий и поле, которое нужно рассмотреть, например: $rep->findByPublished(1) весь остальной код остается прежним, поэтому ваши контроллеры не знают о логике бизнес-уровня например, которые модерируются или нет, и не имеют к этому отношения. то в контроллере администратора вы напишете логику, чтобы установить ревизию в качестве основного сообщения и отменить публикацию старого при его пересмотре. простой, чистый, масштабируемый, поддерживаемый и действительная модель.

CREATE TABLE `wp_posts` (
  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,

  `post_author` bigint(20) unsigned NOT NULL DEFAULT '0',

   `post_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', #date of creation of this post o revision




  `post_status` varchar(20) NOT NULL DEFAULT 'publish', #publish, unpublish, 

  `post_name` varchar(200) NOT NULL DEFAULT '', #internal name if you want to better identify revisions

  `post_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', #date of modification of this current post or revision

  `post_parent` bigint(20) unsigned NOT NULL DEFAULT '0', #if this is a revision, here you have the id of the main post this could replace if it it approved

  `post_type` varchar(20) NOT NULL DEFAULT 'post', //basicaly in your case, post or revision, but you can remove this one, since you can check if post_parent is 0 (or NULL if you want)


  ##Other columns with all the post information 



  PRIMARY KEY (`ID`),

) 

Мне не нравится, как делается WordPress, но я должен сказать, что это отличный подход. И четыре уверены:

  • Даже не думайте о дополнительных столбцах, так как вы сможете сэкономить слишком мало метаданных, а также придется модифицировать базу данных, если вы решите, что некоторые другие столбцы являются элегантными для редактирования.
  • В одном и том же поле не существует более одной ревизии. Это противоречит всем принципам реляционных баз данных. Вы можете иметь сериализованную информацию для некоторых метаданных, и в некоторых случаях это может быть нормально, но для этого есть основная информация, она будет невозможна для обработки и анализа во многих ситуациях.
  • У вас может быть вспомогательная таблица, модель будет действительна, но будет сложнее выполнять поиск, сортировки, и на самом деле у вас будет две таблицы одинаково, поэтому это не лучшая идея.

Ответ 3

Когда произойдет обновление, создайте новую строку и укажите флаг, который должен замещать модератор. Когда модераторы принимают, отметьте принятую запись как активную, а предыдущая запись неактивна. Сделайте это на самом высоком уровне, чтобы, если у вас есть другие таблицы, соединяющие это, они наследуют активное/неактивное состояние и флаг is_moderated.

id | text      | is_active | is_moderated | is_accepted
-------------------------------------------------------
1  | hello     | 1         | 1            | 1             <-- This is the active row

Добавлена ​​новая запись с изменением приветствия на прощание

id | text      | is_active | is_moderated | is_accepted
-------------------------------------------------------
1  | hello     | 1         | 1            | 1             <-- This is still the active row
2  | goodbye   | 0         | 0            | 0             <-- Moderator needs to accept or deny this

Принятый результат:

id | text      | is_active | is_moderated | is_accepted
-------------------------------------------------------
1  | hello     | 0         | 1            | 1             <-- This is NOT the active row
2  | goodbye   | 1         | 1            | 1             <-- Accepted, new active row

Отклонено:

id | text      | is_active | is_moderated | is_accepted
-------------------------------------------------------
1  | hello     | 1         | 1            | 1             <-- This is still the active row
2  | goodbye   | 0         | 1            | 0             <-- Moderator denied

Ваш выбранный запрос будет выглядеть следующим образом:

Чтобы получить активную строку:

SELECT * FROM TABLENAME WHERE is_active = 1

Чтобы получить строки, требующие модерации

SELECT * FROM TABLENAME WHERE is_moderated = 0

Ответ 4

Собственно, ответ не так сложный. Вот моя идея: -

Шаг 1: Просто добавьте столбец в таблицу Posts (или таблицу, содержащую все сообщения пользователей) с именем Moderated Post. Любая модерация или изменения любого модератора попадают в этот столбец.

Шаг 2: Добавьте еще один столбец в таблицу Posts с именем isModerated. Он содержит значение 1 или 0 точно так же, как boolean true или false.

Шаг 3: Теперь вы почти закончили. У вас есть таблица вроде этого: -

                      TABLE `POSTS`

| Post id | Initial Post | Moderated Post | isModerated |
_________________________________________________________
          | The first    |                |             |
|    1    | post goes    |                |      0      |
|         | here         |                |             |
_________________________________________________________
|         | The second   | The moderated  |             |
|    2    | post goes    | post goes here |      0      |
|         | here         |(Post invisible)|             |
_________________________________________________________
|         | The third    | The moderated  |             |
|    3    | post goes    | post goes here |      1      |
|         | here         | (Post visible) |             |
_________________________________________________________

Теперь в вашем php-коде, после извлечения всех значений из таблицы, вы показываете свой пост следующим образом (JUST A ROUGH SKETCH): -

<?php 
if($isModerated == 1) { 
   echo $moderated_post; 
}else {
   echo $initial_post;
}
?>

Для изменений в многочисленных таблицах

Как вы сказали, что модерация изменяет значения в нескольких таблицах, для этого вам нужно добавить столбец (Moderated_Value1) x n, где n обозначает количество столбцов, значения которых могут быть изменены. Пример: -

| Value 1 | Value 2 | Moderated_Value1 | Moderated_Value2 |
|   0     |    1    |      1000        |     2000         |

Теперь ваш код будет выглядеть следующим образом: -

<?php 
if($isModerated == 1) { 
   echo $moderated_post; 
   echo $moderated_value1;
   echo $moderated_value2;
}else {
   echo $initial_post;
   echo value1;
   echo value2;
}
?>

Используя этот метод, есть также преимущество, что вы можете легко отменить модерирование, изменив isModerated значение в таблице от 1 до 0

Ответ 5

Идея: добавьте номер версии для всех таблиц. Когда кто-то вносит изменения, уникальный номер версии этого изменения сохраняется во всех затронутых строках. Вместо обновлений вставлена ​​строка с более высоким номером ревизии и одним и тем же идентификатором. Столбец Id не должен быть уникальным, конечно. Текущий номер активной версии хранится в таблице, которая просто удерживает это число. Затем вы создаете представления БД, которые выглядят как предыдущие таблицы, но если 2 строки имеют одинаковый идентификатор, он получает только запись с самым высоким номером ревизии, который равен или ниже активной ревизии. В вашем приложении вы используете представления вместо исходных таблиц. Затем вы можете просмотреть изменения в исходных таблицах, удалить те, которые вы не принимаете, и поднять текущую активную ревизию, чтобы принять все изменения, которые вы не удалили.

Ответ 6

Вы можете добавить ревизию в свои таблицы и иметь составной первичный ключ

позволяет предположить, что у вас есть эта таблица

id -> Integer PK
comment -> text
user -> integer

если вы добавите эти поля

revision -> integer PK with id
published -> boolean -- this will tell you wich one is active

Вы можете добавить еще несколько полей аудита, например, некоторые даты для проверки, когда создается новая ревизия, или кто создал версию ревизии

и логин, чтобы получить версию, легко выбрать, вы можете выбрать любую ревизию по ее номеру ревизии, или вы можете получить активную...

конечно, это даст вам некоторые проблемы с совпадением (2 человека, изменяющих одну и ту же строку одновременно), но вы можете использовать семафоры или что-то в этом роде), вы не можете продолжать использовать генераторы/автосохранения для своих inserts, (нормально, вы могли бы использовать генераторы ТОЛЬКО для новых записей).

другой способ: если вы не хотите хранить всю историю изменений и нуждаетесь только в последнем выпуске, нужно добавить текстовое поле и сохранить сериализованный массив с отредактированными значениями, и, как вы утверждаете, просто запустите обновить поля.

существует множество способов, вы можете использовать этот пример сериализации и использовать таблицу aux для хранения истории и смешивать оба aproche, помещать в таблицу aux исходный идентификатор, ревизию и сериализованный массив, а вы имеют как... сериализованную версию со всеми ревизиями....

выберите тот, который лучше всего описывает вашу ситуацию....

Ответ 7

Еще одна идея - сохранить все измененные данные в массиве (array [$ table] [$ field] [$ id] = $value), а затем сохранить его в простой таблице с полем типа TEXT в json-кодировке. Таким образом, у вас также будет достаточно гибкости для изменения (добавления) других элементов управления без изменения структуры таблицы редактирования.: -)

Ответ 8

Я думаю, что вы можете легко работать в обратном направлении и выбирать WORST, чтобы увидеть, что является наименее плохим выбором, если вы не думаете, что есть выбор ХОРОШЕЕ. Каждый выбор требует жертв. Но каковы эти жертвы?

Вариант №1. Дублируйте все таблицы (вместе с MyTable и MyTable_ToApply).

ИМО это будет гигантская головная боль. Поговорите о слишком многих областях! Вам также потребуется создать дополнительное кодирование, чтобы переместить данные из одной таблицы в другую. Я думаю, что здесь слишком много, что может пойти не так, как надо.

Вариант № 2: добавьте специальную таблицу (ToApplyTable) с четырьмя полями: таблицу для изменения, поле для изменения, идентификатор записи для изменения и новое значение для применения.

Я думаю, что это также грязный вариант, как вы упомянули, из-за того же: перемещение значений из одной таблицы в другую.

Вариант № 3: добавьте значения date и ismoderated в таблицу.

Об этом говорили многие люди. Ваш аргумент состоит в том, что слишком много (в основном бесполезных) столбцов. Я думаю, что это лучше всего, что было упомянуто. Я смиренно предлагаю один последний метод, который представляет собой комбинацию опций # 1 и опции № 3.

Вариант № 4. Создайте пользовательскую таблицу ismoderated под каждой таблицей, которая может иметь умеренные поля.

Я делаю что-то подобное в своей базе данных и использую стандарт именования [TABLENAME]__ismoderated. В этой таблице вам действительно не нужно больше одного столбца, если вы только хотите. Вы можете просто иметь внешний ключ в этой таблице элементов, которые нужно модерировать, а затем удалить ключ, когда он окончательно модерируется. Кроме того, вы можете добавить здесь идентификатор пользователя модератора и время, добавленное в качестве дополнительных полей, если хотите.

Я лично думаю, что поеду с полем datetime, чтобы у вас была возможность следить за изменениями и знать, какая из них самая последняя.

В любом случае это дает вам возможность INNER JOIN обе таблицы. Если вы хотите, чтобы значения были модерируемыми.

Ответ 9

Было дано много ответов, и я чувствую, что большинство из них очень разумны. Я считаю, что есть несколько хороших способов сделать это.

Я делаю предположения, что мощность/скорость обработки важнее/дороже, чем пространство для хранения как на жестком диске, так и на ОЗУ. Я также согласен с г-ном Роббсом (где-то выше меня), что в каждой строке/ячейке должна быть одна ревизия, а добавление дополнительных столбцов не является правильным решением (см. Ниже для разработки).

Позвольте мне сначала начать с вариантов, которые, как я считаю, не верны:

  • JSON/NoSQL. ваши данные явно реляционные. (мой) SQL - это способ идти.
  • Хранить в виде массива или другой формы памяти приложения. накладные расходы это создает, в том числе бремя для каждого игрока не стоило того. Кроме того, вы хотите иметь возможность хранить это и перебирать эти изменения во времени и сохранение его как части приложений с течением времени. Это просто не стоит.
  • Добавьте один или несколько столбцов, добавленных в каждую таблицу. Созданные изменения могут быть сохранены там. Как вы упомянули, это создает значительных накладных расходов в таблице (таблицах) и является плохой практикой. Тем не менее, это правильное решение, когда, например, нужно редактировать только сообщения или любой другой отдельный объект, и никакая история не должна быть сохранена. Однако в этом вопросе все не так.

Взглянув на факты, представленные в вопросе:

  • есть одна или несколько таблиц с элементами, которые можно модерировать,
  • существует несколько модераторов, которые могут создавать несколько версий
  • эти изменения не всегда применяются в хронологическом порядке.
  • вам может потребоваться вести запись всех предложенных и применяемых записей

Я думаю, что второе решение, которое вы предоставили, наилучшим образом соответствует вашим данным.

  • Создайте отдельную таблицу для ревизий. Это лучший нормализованный способ сделать это. В зависимости от масштаба модерации вы можете либо сохранить копию полной строки, которая редактируется, либо сделать ссылку на конкретные ячейки, которые редактируются.
  • Для дополнительных экспертных уровней вы можете использовать что-то вроде представлений или временных таблиц для создания таблицы со всеми определенными строками и не показывать ожидающие или отклоненные изменения. Это может улучшить скорость, но опираться на серьезную разработку базы данных. Не то, что вы хотите испортить.

Нажатие изменений для ваших пользователей может осуществляться различными способами. Используя приведенную выше временную таблицу/представление, вы используете хранимую процедуру для изменения того, что в таблице (или установите ячейку в "активную" и обновите временную таблицу/представление) Вы можете просто заменить строку в базе данных новой (обновления дорогостоящие) или использовать конструкцию соединения.

Если процессор дешевле хранилища, то поиск системы с git с хешей или так может работать.

Ответ 10

Однако модераторы будут изменять данные с помощью форм.

Когда они меняют данные, почему вы не сохраните данные в файлах csv...

Пока вы изменяете изменения, вы можете вставлять их в фактическую таблицу.

Только идея.