Как написать свою cms: Как я написал свою CMS, и почему не рекомендую вам делать то же самое / Хабр

Содержание

Зачем писать свою собственную CMS?

Учитывая все споры о том, какая CMS является лучшей, я бы хотел потратить некоторое время на то, чтобы изложить свое мнение .

Почти год назад я понял, что мой сайт стареет в зубе. Он должен быть обновлен, и не только дизайн, но и вся функциональная основа того, как контент создается, управляется и публикуется. Он становится слишком большим и сложным, поэтому мне нужна CMS – и почти как только я это понял, я решил написать свою собственную.

Почему я решил написать свой собственный

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

Я также хотел создать сайт, на котором каждая страница может быть синдицирована либо в виде метаданных JSON , либо в виде HTML -содержимого только для контента, и чтобы все, что пользователь должен сделать для получения этого содержимого API, это добавить ".json"".html"URL страницы. Насколько я знаю, ни одна из существующих систем не может сделать это без масштабной модификации.

Я много работал с WordPress, а также хорошо разбирался в установке, которую использует SitePoint – и для того, чтобы все это работало, нужно много плагинов и пользовательский код. Я бы предпочел потратить это время на написание чего-то нового, не в последнюю очередь потому, что мне самому нравится создавать вещи .

Я также ненавижу поля редактирования на основе браузера , и даже самые продвинутые из них не могут сравниться с мощью и гибкостью такого текстового редактора, как BBEdit или TextPad. Когда дело доходит до ежедневного обслуживания и обновлений, у меня есть способ работы и инструменты, которые помогают мне быть продуктивным, и почти все инструменты на основе браузера, которые я использовал, мешают этому. Мой опыт работы с WordPress, безусловно, не помог, так как он постоянно расстраивает и раздражает меня, разрушительно разбирая мою разметку , меняя элементы, добавляя разрывы, делая хороший HTML плохим. Я не хочу иметь дело с этим. Мне нужна система, которая работает с обычными текстовыми файлами, которые вообще не анализируются, и их не нужно очищать, поскольку они не хранятся в базе данных.

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

И ориентированное на пользователя мышление подводит меня к моему последнему, возможно, наиболее важному моменту, который заключается в том, что я хотел сосредоточиться на доступности во всем коде на стороне клиента, который он производит. Системы управления контентом неизбежно являются серверными приложениями, и когда группа разработчиков имеет такую ​​сильную направленность на сервер, клиентская сторона часто стремится уделять такое же внимание деталям. Я видел это много раз почти с каждым CMS и форумным пакетом, который я использовал – когда дело доходит до конфликта между тем, что удобно строить на сервере, и тем, что лучше всего создавать на стороне клиента – сервер всегда выигрывает.

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

Вот как работает Справочник по SitePoint – сложные, подробные страницы генерируются из XML , но все это выполняется заранее для создания по существу статических страниц, и это то, что пользователь извлекает. Я не знаю ни одной CMS, которая бы работала таким образом, и сама SitePoint Reference была индивидуальным решением (в основном разработанным Кевином Янком ).

Преимущества написания своего собственного

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

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

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

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

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

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

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

Недостатки написания своего собственного

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

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

Даже простая CMS занимает очень много времени для сборки . Я знал, что это никогда не будет тривиальной задачей, но я с самого начала не предполагал, сколько времени будет потрачено на написание функций администратора . Оглядываясь назад, должно было быть очевидно, что создание инструментов администратора будет (и было) около 90% работы. Время от времени на разработку этой системы у меня уходило полгода , и я бы соврал, если бы сказал, что все это время у меня была мотивация!

И из-за этого, а также в результате акцента, который я сделал на выводе на стороне клиента, некоторые из моих процессов администрирования на стороне сервера невероятно тупы . Конечно, это не влияет на пользователей – когда дело доходит до просмотра страниц, я сделал эти процессы максимально удобными и эффективными. Но некоторые функции администратора – это медленный, не элегантный код, который я не любил писать и просто хотел, чтобы это было сделано. Если бы я на самом деле выпускал этот код для использования другими людьми, я бы никогда не принял его. Только потому, что только для меня, и только на самом деле влияет на меня, я могу игнорировать такие вещи.

Вывод

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

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

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

Если вам понравилось читать этот пост, вы полюбите Learnable ; место, чтобы узнать новые навыки и приемы у мастеров. Участники получают мгновенный доступ ко всем электронным книгам и интерактивным онлайн-курсам SitePoint, таким как «Руководство для начинающих по веб-дизайну с WordPress» .

Миниатюра кредит: Майк Прокарио

php — Как спроектировать и построить свой движок для сайта(CMS)

Пишу специально для своего сайта но универсальный.
Так что хочу узнать теоретические вопросы построения движка.
Вопросы:

  1. Как спроектировать архетектуру?
  2. Как написать модульную расширяемую cms?
  3. Стоит ли писать для него фреймворк?
  4. Как должна выглядеть БД
  • php
  • cms
  • mysql






2

  1. Используйте паттерны проектирования, для сайтов хорошо подходит MVC. Используйте готовый http-сервер, наиболее простой и производительный вариант связи с сервером — fastcgi. Хороший http-сервер должен уметь обрабатывать запросы параллельно.
  2. Реализуйте шаблоны страниц и возможность подключать внешние библиотеки, скрипты и программы. Задокументируйте API для всего этого.
  3. Можете взять готовый, если нет подходящего — пишите свой.
  4. БД зависит от цели сайта, но может содержать и предопределённую часть структуры, обычно это список пользователей и прав. СУБД должна обеспечить параллельность запросов.

Всё зависит от Вас:

  1. Как Вам удобнее.
  2. Какие Вы имеете знания.
  3. Для чего Вам нужен этот сайт.
  4. Какие технические решения Вы будете использовать.

Список можно продолжать до бесконечности; но если Вы думаете что Вам сейчас напишут план разработки CMS, то Вы ошибаетесь.


Главное ИМХО — знание ООП, HTML, XML, а подробнее можно узнать, ковыряя уже кем-то написанные CMS






5







Зарегистрируйтесь или войдите

Регистрация через Google

Регистрация через Facebook

Регистрация через почту

Отправить без регистрации

Почта

Необходима, но никому не показывается

Отправить без регистрации


Почта

Необходима, но никому не показывается




Нажимая на кнопку «Отправить ответ», вы соглашаетесь с нашими пользовательским соглашением, политикой конфиденциальности и политикой о куки


Как построить CMS с использованием JavaScript с Contacuful

  • Developers

  • Стратегия
  • Продукт
  • Партнеры
  • Блог Дом

Разработчики

.

Bulent Yusuf

Категория

Разработчики

Темы

JavaScriptGuidesHeadless CMSProfessional Developer

Система управления контентом (CMS) позволяет редактору веб-сайта управлять контентом без технических знаний. CMS также позволяет быстро просмотреть статус вашего контента — активен ли он, неопубликован или находится в процессе проверки.

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

В эпоху Web 2.0 была создана монолитная, связанная (все-в-одном) CMS, которая включала все необходимое для организации и публикации веб-контента. Однако это решение было разработано для доставки веб-контента на настольные компьютеры, и последующее распространение мобильных устройств и устройств IoT поставило под вопрос его эффективность.

Затем возникла несвязанная и безголовая CMS. Эта новая модель позволила разработчикам работать с интерфейсом веб-сайта, не затрагивая его содержимое.

Теперь, когда инструменты CMS являются неотъемлемой частью управления веб-сайтом, некоторые поставщики CMS предлагают возможности API, позволяющие разработчикам создавать собственные платформы CMS. Одним из таких примеров является Contentful Content Management API, который вы изучите в этом руководстве.

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

Можете ли вы создать CMS с помощью JavaScript?

Безусловно! В этом руководстве вы узнаете, как создать приложение JavaScript CMS, которое подключается к API управления контентом Contentful. Предпосылки для прохождения:

  • Базовое понимание приложений, созданных с помощью Node. js и Express.js.

  • Созданное контентное пространство и ключ API для хранения и извлечения контента из вашего пространства.

  • Личный токен аутентификации.

  • Доступ к Postman для тестирования.

Полный код проекта можно найти на GitHub.

Начало работы 

Чтобы начать, выполните следующие действия, чтобы установить и настроить новый проект.

Сначала создайте новый каталог для своего проекта и перейдите в него.

Теперь откройте терминал в этом каталоге и выполните приведенную ниже команду.

Это проведет вас через шаги по добавлению файла package.json в ваш каталог.

Теперь вы добавите несколько дополнительных пакетов для этого проекта.

Выполните следующие команды в своем терминале, чтобы установить Express.js и Nodemon, который отслеживает изменения файлов.

В этом руководстве также будут использоваться другие пакеты npm: dotenv для хранения токена, axios для выполнения HTTP-запросов к API и управление контентом для использования встроенных функций Contentful. Позже вы будете использовать Postman для тестирования конечных точек API.

Для установки модулей используйте следующую команду:

После установки пакетов создайте новый файл index.js в корневом каталоге. Это будет основной файл в вашем приложении Node.

Прежде чем писать какой-либо код в файле index.js , вам необходимо настроить Nodemon так, чтобы он указывал на файл index.js .

Откройте файл package.json и добавьте следующую строку в раздел сценариев:

Сохраните файл.

Затем, чтобы сохранить переменные среды, создайте новый файл с именем .env в корневой папке для хранения токенов CMA и CDA. В этом файле создайте две переменные и замените текст-заполнитель вашими токенами, которые вы можете получить, следуя этому руководству:

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

После добавления стандартного кода сохраните файл index. js .

Теперь создайте новую папку /routes в каталоге вашего проекта и создайте новый файл с именем cmsroutes.js в папке маршрутов.

Затем добавьте следующий код в файл cmsroutes.js :

Теперь базовое приложение готово к следующим шагам. Откройте терминал в каталоге вашего проекта и выполните следующую команду, чтобы запустить сервер Node:

( Примечание : Поскольку вы еще не добавили маршруты, не рекомендуется тестировать ответ сервера в браузере, так как он вернет ошибку.)

Создание приложения JavaScript, которое аутентифицируется в вашей учетной записи Contentful в этом и последующих разделах вам понадобится ваш Space ID. Вы можете найти свой Space ID при создании токена или следуя этому руководству.

Теперь откройте каталог маршрутов. Затем в файл cmsroutes.js добавьте следующий код, чтобы создать новый маршрут:

В этом коде вы создали маршрут для аутентификации пользователя, который входит в определенное пространство в своей учетной записи Contentful. Аутентификация выполняется с использованием токена CDA, который вы передали в заголовках вместе с вашим запросом к серверу Contentful. Основываясь на ответе Contentful, пользователь уведомляется, авторизован ли он для входа в систему.

Теперь, когда вы создали маршрут и метод, пришло время протестировать API в Postman, популярном инструменте тестирования API. После загрузки Postman вы можете добавить URL-адреса, типы запросов и заголовки для проведения тестирования API.

Ниже приведен пример Postman в действии.

Обратите внимание, что строка после authUser — это space_id . Чтобы создать этот запрос в Postman, вы можете добавить следующее в адресную строку: 

Успешный ответ API возвращает строку: Вы авторизованы для входа!!

Добавление типов контента в ваше пространство

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

Теперь вы можете добавить тип контента в свое пространство. Начните с создания нового маршрута в route/cmsroutes.js :

В приведенном выше коде :space_id передает идентификатор вновь созданного пространства, :environment_id передает идентификатор вашей среды (основной) и :content_type_id — это определяемое пользователем имя вашего типа контента.

Обратите внимание, что в заголовке вы передаете два параметра:

Теперь, когда маршрут создан, проверьте его в Postman, используя URL:

Убедитесь, что тип запроса установлен на PUT, а тип тела запроса — JSON.

Тело запроса:

В ответ вы получили: 

Портал контента создаст такой тип контента:

Добавление нескольких полей к вашему типу контента

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

Для этого создайте новый маршрут в файле route/cmsroutes.js , добавив следующий код:

Здесь вы передаете :space_id , :environment_id и :content_type_id. Вы также передаете три параметра в своем заголовке:

  • Авторизация: `Bearer ${process.env.CMA_ACCESS_TOKEN}`

  • "content-type": "application/vnd.contentful.management. v1+json"

  • "X-Contentful-Version":content_version , который будет получен из тела запроса

Третий параметр, X-Contentful-Version , отслеживает версию созданного типа контента. При каждом обновлении номер версии увеличивается.

Теперь, чтобы проверить маршрут в Postman, добавьте следующий URL-адрес:

Опять же, убедитесь, что для типа запроса установлено значение PUT.

Тело запроса должно быть следующим:

Затем Postman предоставляет этот ответ:

Ваша модель контента должна выглядеть примерно так:

Валидации

При создании или изменении типа контента определение проверки поля позволяет вы, чтобы предотвратить ошибки.

Вы можете использовать тот же маршрут, который использовался для добавления полей в тип контента. Однако при передаче объекта JSON в теле запроса вы также добавите проверки в дополнение к полям, используя следующий код:

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

Затем пользовательский интерфейс Contentful показывает проверку.

Активация типа контента

Вы можете изменить статус типа контента с Черновик на Активный. Чтобы активировать тип контента, сначала добавьте новый маршрут в свой route/cmsroutes.js файл. Затем добавьте следующий код:

В приведенном выше коде вы использовали встроенную библиотеку Contentful и инициализировали ее, добавив contentful.createClient в файл cmsroutes.js .

Параметры вроде :space_id , :environment_id и :content_type_id также передаются, как и в других маршрутах. Библиотека Contentful позаботится обо всем остальном.

Теперь вы можете протестировать маршрут для активации типа контента в Postman, используя следующий URL-адрес:

В теле ответа Postman вы увидите, что он активирован! Портал Contentful CMS установит тип контента как АКТИВНЫЙ.

Получение интерфейса редактора для типа контента

Интерфейс редактирования представляет внешний вид и поведение типа контента в веб-приложении Contentful. Каждая категория типа контента может иметь только один интерфейс редактирования. API вернет ошибку 404, если тип контента еще не активирован.

Чтобы получить интерфейс, сначала установите новый маршрут в route/cmsroutes.js , добавив следующее:

Как и в случае с другими маршрутами, вы передали в маршрут два аргумента: :space_id и :environment_id .

Кроме того, заголовок содержит ваш CMA (токен Contentful Management API):

Путем тестирования маршрута в Postman с использованием URL-адреса 127. 0.0.1:8000/editorInterfaces/{space_id}/{environment_id} и установки типа запроса как GET , вы получите следующий ответ:

Обновление интерфейса редактора для типа контента

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

Чтобы начать вносить изменения, добавьте следующий код в файл route/cmsroutes.js :

В маршрут вы передали три параметра: space_id , environment_id и content_type_id .

Теперь так же, как добавление полей в content_type , вы передадите три параметра в заголовке вашего запроса:

  • Authorization: `Bearer ${process.env.CMA_ACCESS_TOKEN}`

  • "content/vnd": contentful.management.v1+json"

  • "X-Contentful-Version":`${req.body.content_version}`

следующий фрагмент кода для тела:

По умолчанию поле заголовка установлено как: Markdown.

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

Теперь внешний вид поля заголовка настроен на: Несколько строк.

Доставка содержимого

Теперь вы можете получить все пространства, созданные в вашей организации. Вы сделаете это с помощью API доставки контента (CDA), который в основном используется для извлечения вашего контента. Он работает так же, как CMA.

Для этого сначала создайте новый маршрут в route/cmsroutes.js , используя следующий код:

Параметры, которые вы передали, аналогичны предыдущим маршрутам, но на этот раз вы передали токен CDA вместо токена CMA в URL вашего маршрута.

Выполнив маршрут в Postman с этим URL-адресом:

, вы должны получить ответ, как показано на изображениях ниже:

Как видите, ответ Postman идентичен использованию токена CDA.

Подведение итогов

Вы видели, как легко создать приложение JavaScript CMS, которое соединяется с Contentful Content Management API. Но вы едва поцарапали поверхность. Contentful предлагает широкий спектр API и SDK.

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

Начни!

Начните строить с бесплатной учетной записью Contentful, кредитная карта не требуется.

Регистрация

Темы

JavaScriptGuidesHeadless CMSProfessional Developer

Об авторах

Элвин Брайан

ВЕБ-САЙТ

TWITTER LINK

0005

Бюлент Юсуф

ВЕБ-САЙТ

GITHUB

LINKEDIN

Начните бесплатно

Зарегистрируйте бесплатную учетную запись Contentful за считанные минуты.

Начало работы

Не пропустите последние новости

Получайте обновления на свой почтовый ящик

Ежемесячно получайте новые идеи от сообщества разработчиков Contentful.

Узнать больше

Разработчики

Что такое TypeScript и зачем его использовать?

18 августа 2022 г. Харшил Агравал

Разработчики

Учебное пособие по Ruby on Rails: Начало работы с Contentful

8 сентября 2022 г. Лукас Шталь

Начните бесплатно

Зарегистрируйте бесплатную учетную запись Contentful за несколько минут.

Начало работы

Контентные мероприятия

Присоединяйтесь к нашим вебинарам, встречам, конференциям и партнерским мероприятиям!

Просмотреть все текущие события

Разработчики

Что такое фреймворк? Все о программных фреймворках

16 августа 2022 г. Лукас Шталь, Шон Хиггинс

Разработка собственной системы управления контентом — Предисловие

Вы можете задаться вопросом, зачем это делать, почему бы не использовать то, что уже доступно на рынке. Почему вы хотите изобретать велосипед? И вы абсолютно правы, на рынке существует множество продуктов для систем управления контентом (также известных как CMS), которые вы можете использовать «из коробки». Вы должны быть в состоянии найти то, что соответствует вашим потребностям и быть счастливым.

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

фото Марко Джалло

Фон

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

Этот проект является одной из систем управления общением с клиентами, в которой особое внимание уделяется универсальному интернет-подходу. Итак, все, что вам нужно, — это веб-браузер, чтобы начать подготовку сообщения по широкому кругу каналов (таких как PDF-файлы, электронная почта, веб-страницы и т. д.).

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

А потом мы врезались в стену!

Тупик

Вскоре стало ясно, что с выбранным решением CMS не удастся реализовать одно из очень простых требований:

  • контент, используемый в шаблоне (или другой контент), не может быть удален пользователем

Что это значит? Это означает, что когда вы разрабатываете свой шаблон сообщения, вы можете комбинировать различное содержимое в шаблон, который можно использовать для подготовки сообщения и, в то же время, никто не должен иметь возможность удалить какое-либо содержимое, используемое шаблоном. Очень простое и логичное требование. Тем не менее, этого нельзя достичь с помощью большинства CMS, поскольку они рассматривают контент как отдельные активы, независимые друг от друга.

Стандартная CMS обычно поддерживает файловую навигацию и структуры (файлы и папки), которые просты в использовании пользователями. Тем не менее, ни один из них не дает вам возможности проверить отношения родитель-потомок, что было еще одним требованием для реализации:

  • система разрешений на основе папок

Были и другие требования, которые мы не смогли выполнить с выбранным решением CMS. Тогда мы решили внедрить собственную CMS.

Отношения

Мы искали решение, которое позволило бы нам легко заставить эти отношения работать:

  • Кто является родителем этого актива?
  • Кто дети этой папки?
  • Для чего используется этот актив?
  • Где используется этот актив?

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

ПРИМЕЧАНИЕ : под активом я подразумеваю любой шаблон, контент, файл, изображение, которые можно было бы создать в системе или загрузить в нее.

Если вы внимательно посмотрите на эти требования, вы получите такие отношения:

  • parentOf & childOf — для представления отношений папка-файлы
  • использует & usedBy — для представления отношения использования актива к активу (контент использует изображение , изображение используется контентом , шаблон использует контент , контент используется шаблоном )

Теперь вы должны быть уверены что единственный способ заполнить их — использовать базу данных Graph. Мы решили использовать Dgraph.

Хранилище

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

  • текст — JSON-представление определения актива
  • двоичный файл — используется для изображений и PDF-файлов

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

Свяжите вещи

Выбрав новый стек технологий, осталось разработать новую CMS. Dgraph поддерживает транзакции, а Cassandra — нет, поэтому наш алгоритм выполнения обновлений должен был выглядеть следующим образом:

  1. начать транзакцию Dgraph
  2. записать данные в Cassandra
  3. затем записать данные в Dgraph
  4. наконец зафиксировать транзакцию

Используя такой подход, мы должны иметь стабильные данные в Dgraph с потенциальными потерянными данными в Cassandra, приемлемое решение.

Реляционная модель

Нашей первой задачей было узнать, как использовать Dgraph, но с их пошаговым руководством это было довольно легко сделать. Dgraph поддерживает GraphQL, но когда мы начали его использовать, такого функционала не было. За две недели мы получили базовые знания о том, как использовать Dgraph, как писать запросы и мутации (запросы, изменяющие состояние). Мы познакомились с тройками Dgraph, как использовать встроенную поддержку JSON и так далее.

Честно говоря, после двух лет использования Dgraph я наконец-то могу сказать, что умею это делать. Никакие учебники и документы не дают такого уровня уверенности, кроме практики.

Имея базовое понимание Dgraph, нам пришлось реализовать очень простую модель для представления отношений. В мире Dgraph вы оперируете узлами и ребрами или предикатами. Узел — это ваша сущность, где ребро/предикат — это отношение с другими объектами — объект может быть другим узлом или скалярным значением (имя узла).

Узлы и ребра/предикаты

Для представления структуры папка-файл нам нужны всего две сущности:

  • контейнер узел, который может содержать другие узлы (например, корневая папка, папки)
  • ан узел актива , который представляет актив (шаблон, контент, изображение, PDF)

Внутри Dgraph использует Uid (универсальный идентификатор) для идентификации каждого узла и представления отношений между различными узлами. Для выполнения основных требований каждый узел в нашей системе должен иметь такие предикаты:

  • parentOf: List[Uid]
  • childOf: List[Uid]
  • Uses: List[Uid]
  • usedBy: List[Uid]

ПРИМЕЧАНИЕ : мы начали с Dgraph 1.0, где были только отношения «один ко многим», поэтому отношение childOf использует список List вместо одного Uid для представления отношения «один к одному». В следующем крупном выпуске Dgraph была добавлена ​​поддержка отношений один к одному, и было бы хорошо когда-нибудь изменить нашу модель отношений.

Помимо этих отношений, мы также определили несколько других скалярных отношений, таких как:

  • uid
  • имя
  • тип узла
  • кто его создал
  • когда узел был создан
  • состояние актива

и так далее.

отношения родитель-потомок и использование-использование

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

Object-Relational Mapping Framework

Поскольку вся модель состояла всего из двух объектов, а Dgraph поддерживает JSON «из коробки», и мы использовали Scala, реализация простого ORM на основе существующего Java-клиента Dgraph была довольно простой задачей. . Мы сделали предположение, что нужно получить всю структуру папок сразу со всеми дочерними элементами. Это дало нам возможность легко перемещаться по всему поддереву папки.

Как только мы начали внедрять нашу ORM, , мы также реализовали крошечный DSL для создания DQL-запросов с поддержкой проверки типов во время компиляции вместо того, чтобы работать только с конкатенацией строк.

В основе ORM было всего три функции:

findBy

 def findBy[T:Decoder](
  запрос: DgraphQuery // <-- наш DSL
)(неявная передача: AsyncTransaction): Future[CmsResult[List[T]]] = {
  tx.queryWithVars (query.toQueryString, query.getValuesMap.asJava)
    . toScala
    .карта {рез =>
      неявное значение dgraphResultDecoder: Decoder[DgraphResult[T]] =
         производный декодер
      значение json = res.getJson.toStringUtf8
      декодировать [DgraphResult [T]] (json)
    }
    .flatMap {
      case Left(ошибка) =>
        CmsResult.failed(ошибка).pure[Будущее]
      случай Правый(r) =>
        CmsResult(r.result).pure[Будущее]
    }
} 

buildMutation

 def buildMutation[T: Encoder](активы: List[T]): Mutation = {
  val setJson = assets.asJson.noSpaces
  Мутация
    .newBuilder()
    .setSetJson(
      байтовая строка
        .copyFromUtf8 (setJson)
    )
    .строить()
} 

executeMutation

 def executeMutation(
  мю: Мутация
)(неявная передача: AsyncTransaction): Future[List[Uid]] = {
  tx.mutate(mu).toScala map {результат =>
    результат.getUidsMap.asScala
     .ценности
     .foldLeft(List[Uid]()) { (акк, значение) =>
       акк :+ Uid(значение)
     }
  }
} 

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