Как правильно хранить тексты постов в БД?

*Преамбула и много воды*
Длительное время я зарабатывал себе шекели на рандомных заказах, большая часть из которых — веб-приложения да АИС. А тут я захотел себе пет-проект в формате агрегатора контента. Соответственно, раз агрегатор контента, значит надо дать пользователю возможность писать посты, вставлять картинки и всячески извращаться с текстовым редактором. Пользователь накатал себе чудо пост, а теперь вопрос:

А как этот пост хранить в бд?

Я перечитал кучу материала и статей на эту тему, но везде мнения либо старые, либо странные, либо вроде норм, а вроде не норм. Общей методики я оттуда не вычленил. Каждый хранит, как хочет, а потом сам же сношается с вытекающими из своих костылей проблемами остаток жизни.

В голову мне пришло пока только два более-менее адекватных варианта:
1) Это хранить пост плейнтекстом прямо в БД. То есть, условный <p>Lorem ipsum</p> будет храниться в БД вместе с <p></p>. Точно так же будут храниться изображения, теги форматирования и прочее. Вроде удобно: достал из БД и сразу в готовом виде засунул в страницу.
В то же время такой способ бесконечно уязвим ко всяким CSRF и XSS и требует дезинфицировать себя сначала на клиенте, потом на сервере перед записью в БД, после этого снова на клиенте перед внедрением в страницу.

2) Это разбить пост на блоки (заголовок, изображение, текст и т.д.) и хранить каждый блок отдельной записью в БД.
Выглядит красиво, и к XSS менее уязвим, да только:
— морока с тем, чтобы собирать пост из блоков;
— если пост большой, то в нем много блоков, а следовательно много запросов к БД;
— растущие проблемы с производительностью при расширении проекта. Взять тот же хабр: 8-минутная статья в среднем будет содержать 30-40 блоков, в год постится 20тыс. постов, итого за пять лет наберется 35 х 20 000 х 5 = 3 500 000 записей чисто с блоками. И каждый день миллион пользователей будут открывать свою ленту и проходиться по этим трем миллионам записей с блоками, чтобы сервер собрал им красивую статейку на 8 минут чтения.
— как сохранить форматирование текста внутри блоков?

Дополнительно:

такой способ бесконечно уязвим ко всяким CSRF и XSS и требует дезинфицировать себя сначала на клиенте, потом на сервере перед записью в БД

Или?

  • 3 500 000 строк — это не то количество, при котором будут возникать проблемы (тем более, что это будет простейшая выборка). А 999 999 пользователей за конкретный день получат сгенерированный первым пользователем HTML из кэша.
  • требует дезинфицировать себя сначала на клиенте, потом на сервере перед записью в БД, после этого снова на клиенте перед внедрением в страницу.

    Для чего? Почистил от лишнего и положил в БД. Зачем ещё в 2 местах городить огород?

  • Алексей Ярков, Я бы посоветовал экранировать XSS инъекции непосредственно при выводе, а не при записи.
  • Ну какбэ есть всего два подхода:
    1. Свой формат: классика типа bb-тегов или даже тупо markdown. Формат строгий а потому никаких проблем, кроме ограниченности.
    2. Чищеный html: если будешь сам велосипедить "очищалку" - гарантировано поимеешь дырки в безопасности, а если использовать какую-то проверенную и поддерживаемую либу - то шанс попасть минимален.

    Использовать json'чик с данными разбитыми по частям можно, но для постов произвольной и вариативной начинки это бессмысленно всё усложнит. Такое используется обычно как связка: конкретные данные + форм-генератор строящий интерфейс по схеме.

    • То бишь, в БД у нас есть поле content, куда запихивают либо данные в markdown, либо данные в виде HTML-разметки, я правильно понял?
      Меня смущает именно факт хранения разметки в БД, как-то уж по-колхозному это выглядит
    • EugeneNail, это всё просто текст, почему бы его там не хранить?
      Порой параллельно ещё хранят полностью очищенный от тегов текст - для поиска.

    Ответы:

    1.!

    2 -это какой-то франкенштейн

    можно заглянуть в движки популярных форумов типа invision powerboard, phpbb и т.п.
    там давно уже выстроилась "косоплечая" конструкция хранения html с тэгами bbcode в комментариях - чтобы при редактировании сообщения вернуть назад bbcode, а не чистый html

    Нормальных подходов всего два - чистить текст перед сохранением в БД или сохранятьть как есть, а чистить перед выводом.
    Оба имеют свои плюсы и минусы. Чаще применяют второй. Иногда чистят и до и после, но чиску до сохранения делают осторожно и нежно. Потому что если найдутся косяки в "чистилке", то второй подход не убьет пользовательские данные.

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

    ...8-минутная статья в среднем будет содержать 30-40 блоков, в год постится 20тыс. постов, итого за пять лет наберется...

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

     

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

     

      • Как правильно хранить тексты постов в БД?Есть ответ
      • 07.04.2024
      Ответить

      Для хранения текстов постов в базе данных рекомендуется использовать тип данных TEXT или VARCHAR, в зависимости от объема текста и требуемой длины строки.

      Если тексты постов могут быть довольно большими, то лучше использовать тип данных TEXT, который позволяет хранить тексты переменной длины до 65,535 символов. Если же тексты не такие объемные, то можно использовать тип данных VARCHAR с заданной максимальной длиной строки.

      Пример создания таблицы для хранения текстов постов в MySQL с использованием типа данных TEXT:

      CREATE TABLE posts (
          id INT AUTO_INCREMENT PRIMARY KEY,
          title VARCHAR(255),
          content TEXT
      );

      При добавлении нового поста в базу данных, текст поста следует экранировать для предотвращения SQL-инъекций. Для этого можно использовать подготовленные запросы или функцию для экранирования специальных символов, доступную в большинстве языков программирования.

      Пример добавления нового поста в базу данных с использованием подготовленного запроса в PHP и MySQLi:

      $title = "Название поста";
      $content = "Текст поста";
       
      $stmt = $mysqli-&gt;prepare("INSERT INTO posts (title, content) VALUES (?, ?)");
      $stmt-&gt;bind_param("ss", $title, $content);
      $stmt-&gt;execute();

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

    Оставить комментарий