Я создаю CMS и пытаюсь найти лучшую архитектуру данных для поддержки функции «сохранить как черновик».
Допустим, у меня есть post
стол. Мне нужна возможность сохранить публикацию как черновик и опубликовать ее при необходимости. Если запись была сохранена как черновик, мы увидим опубликованную версию публикации. При редактировании этого сообщения мы увидим черновую версию с возможностью сохранить ее как черновик или опубликовать.
Проведя небольшое исследование, я наткнулся на следующие варианты архитектуры данных:
Опция 1
post
id
title
body
status
post_draft
id
title
body
post_id
При создании поста мы вставляем строку в обе таблицы. При просмотре публикации мы просматриваем таблицу post
. При редактировании поста мы смотрим в таблицу post_draft
, есть ли черновик. При сохранении черновика мы обновляем таблицу post_draft
, а при публикации копируем содержимое post_draft
в соответствующую публикацию.
Я попробовал это, и это работает хорошо, но у него есть недостаток: приходится поддерживать две одинаковые таблицы. Поэтому, если в будущем мне понадобится добавить столбец в сообщение, мне нужно будет добавить его в обе таблицы.
Однако он аккуратно разделяет опубликованные и черновые сообщения.
Вариант 2
post
id
post_content
title
body
status
post_id
Здесь у нас есть одна таблица для сообщения, и мы извлекаем ее содержимое в зависимости от того, какой статус мы хотим получить. Если нам нужна черновая версия, присоединяемся к post
и post_content
с помощью status = "draft"
.
Это тоже работает хорошо, но тогда такие вещи, как индексирование и поиск, становятся немного сложнее. Это также усложняет другие задачи, которые мне нужно сделать, например, возможность возвращать несколько таблиц за один запрос (я не буду вдаваться в подробности — достаточно сказать, что это усложняет некоторые другие требования).
Вариант 3
post
id
title
body
status
published_id
Здесь у нас есть только одна таблица. Чтобы получить опубликованную версию публикации, мы искали идентификатор с status = "published"
. Для поиска черновой версии ищем status = "draft"
и published_id=[the post id]
.
Кажется, это решает ряд проблем. Единственный недостаток, который я вижу, это то, что идентификаторы опубликованных сообщений будут прыгать повсюду.
Есть ли передовая практика для реализации чего-то подобного? Есть какие-нибудь предпочтительные варианты или что-то, что я не рассмотрел?
Третий вариант – лучший вариант и, с моей точки зрения, единственно правильный. Содержимое DRAFT и LIVE одинаково и различается только одним свойством — статусом. Представьте себе ситуацию, когда вам нужно будет добавить новый статус типа «ПРИНЯТО», «УДАЛЕНО» и т. д. Вероятно, вы не захотите создавать для этого новые таблицы, потому что обработка этого будет кошмаром.
Почему вы считаете пропуск идентификаторов проблемой? Это не проблема для базы данных, и номера сообщений, если вы хотите, чтобы они были последовательными, вы можете добавить, например, столбец post_number.
@ Хьюберт, я столкнулся с похожей проблемой: как вы справились с ситуацией, когда состояние публикации и черновика одновременно совпадают? Если вы публикуете объявление, а затем что-то в нем меняете, но предпочитаете сохранить изменения в состоянии черновика. Таким образом, пользователь по-прежнему должен видеть старую опубликованную версию, в то время как в бэк-офисе администратор может видеть черновую версию.
@LM_IT, я использовал вариант 3, как описано в моем первом посте. Допустим, у вас есть опубликованное сообщение с идентификатором = 3. Когда вы сохраняете его как черновик, вы создаете новую запись в таблице «пост». Это будет точная копия записи №3, за исключением того, что идентификатор будет другим, «статус» будет «черновик», а «published_id» будет 3. Таким образом, опубликованные и черновики сообщений существуют одновременно.
Спасибо, протестировав все три варианта, я согласен, что третий является наиболее гибким и практичным в реализации. Поэтому я решил пойти на это.