*Преамбула и много воды*
Длительное время я зарабатывал себе шекели на рандомных заказах, большая часть из которых — веб-приложения да АИС. А тут я захотел себе пет-проект в формате агрегатора контента. Соответственно, раз агрегатор контента, значит надо дать пользователю возможность писать посты, вставлять картинки и всячески извращаться с текстовым редактором. Пользователь накатал себе чудо пост, а теперь вопрос:
А как этот пост хранить в бд?
Я перечитал кучу материала и статей на эту тему, но везде мнения либо старые, либо странные, либо вроде норм, а вроде не норм. Общей методики я оттуда не вычленил. Каждый хранит, как хочет, а потом сам же сношается с вытекающими из своих костылей проблемами остаток жизни.
В голову мне пришло пока только два более-менее адекватных варианта:
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 и требует дезинфицировать себя сначала на клиенте, потом на сервере перед записью в БД
Или?
Написано
Алексей Уколов
@alexey-m-ukolov Куратор тега Веб-разработка
3 500 000 строк — это не то количество, при котором будут возникать проблемы (тем более, что это будет простейшая выборка). А 999 999 пользователей за конкретный день получат сгенерированный первым пользователем HTML из кэша.
Ну какбэ есть всего два подхода:
1. Свой формат: классика типа bb-тегов или даже тупо markdown. Формат строгий а потому никаких проблем, кроме ограниченности.
2. Чищеный html: если будешь сам велосипедить "очищалку" - гарантировано поимеешь дырки в безопасности, а если использовать какую-то проверенную и поддерживаемую либу - то шанс попасть минимален.
Использовать json'чик с данными разбитыми по частям можно, но для постов произвольной и вариативной начинки это бессмысленно всё усложнит. Такое используется обычно как связка: конкретные данные + форм-генератор строящий интерфейс по схеме.
То бишь, в БД у нас есть поле content, куда запихивают либо данные в markdown, либо данные в виде HTML-разметки, я правильно понял?
Меня смущает именно факт хранения разметки в БД, как-то уж по-колхозному это выглядит
можно заглянуть в движки популярных форумов типа invision powerboard, phpbb и т.п.
там давно уже выстроилась "косоплечая" конструкция хранения html с тэгами bbcode в комментариях - чтобы при редактировании сообщения вернуть назад bbcode, а не чистый html
Нормальных подходов всего два - чистить текст перед сохранением в БД или сохранятьть как есть, а чистить перед выводом.
Оба имеют свои плюсы и минусы. Чаще применяют второй. Иногда чистят и до и после, но чиску до сохранения делают осторожно и нежно. Потому что если найдутся косяки в "чистилке", то второй подход не убьет пользовательские данные.
Идея с разбивкой на блоки выглядит стремно - нужно или очень жестко ограничивать структуру постов, или вы задолбетесь предусматривать все пользовательские хотелки. По сути вы хотите свой язык разметки изобрести, но не очень понятно зачем.
...8-минутная статья в среднем будет содержать 30-40 блоков, в год постится 20тыс. постов, итого за пять лет наберется...
кеширование, не? Уже скомпилированную статью можно сохранить в готовый файлик или отдельную таблицу, и испорльзовать пока ее не отредакритруют. Но опять-же, зачем вся эта возня со своим языком разметки и компиляцией если можно просто сохранить текст с разметкой?