Давайте дадим нашим схемам баз данных больше свободы
MongoDB - отличный выбор для ряда приложений. В мире PHP мы также можем попробовать нечто большее, чем просто стек LAMP, и дать нашим схемам базы данных больше свободы. Одним из самых популярных объектно-реляционных сопоставителей (ORM) для PHP является Doctrine, который также имеет очень хорошую реализацию Object Document Mapping (ODM) для MongoDB. Мы не будем вдаваться в подробности о преимуществах или недостатках баз данных NoSql и SQL, но посмотрим, как мы можем создать очень простое приложение, если мы уже решили использовать Mongo.
Полный исходный код доступен в следующем репозитории:
Нам необходимо создать приложение корзины покупок с REST API, которое позволит нам:
- добавить новый товар в каталог
- обновить название продукта
- создать новую корзину
- добавлять и удалять товары из корзины покупок
- записывать, когда товар был добавлен в корзину
Также у нас есть набор требований:
- цена продукта должна быть положительной и указана валюта EUR, PLN или USD.
- у нас может быть только один товар данного типа в корзине и не более 4 товаров одновременно
Мы будем использовать фреймворк Symfony, поскольку он прекрасно интегрируется с Doctrine ODM. Мы можем установить библиотеку и сгенерировать базовую конфигурацию, выполнив следующие команды:
composer config extra.symfony.allow-contrib true composer require doctrine/mongodb-odm-bundle
Мы будем обращаться к базе данных таким же образом, как и с ORM в Doctrine. Мы используем аннотации в моделях, которые укажут, какие переменные класса следует сохранить. В нашем Product
мы указываем имя, цену и валюту в качестве аргументов конструктора. Не требуется особой логики, поэтому класс очень простой.
По умолчанию коллекция имеет то же имя, что и модель, которая ее использует. Мы можем настроить это поведение, указав параметр collectionName
в аннотации Document
. Мы также можем хранить несколько разных моделей в одной коллекции, поскольку MongoDb очень гибок, когда дело касается схемы базы данных.
Product
получает проверенные объекты значений, которые обеспечивают правильность данных. Мы не будем вдаваться в подробности их реализации, их можно найти на Github.
Doctrine ODM делает оптимистичную блокировку чрезвычайно простой. Этот механизм гарантирует, что никто не изменил модель одновременно с нами, сравнивая атрибут version
. Все, что нам нужно было сделать, это поставить одну аннотацию @ODM\Version
.
Модель корзины для покупок немного сложнее, поскольку мы должны обеспечить соблюдение всех правил, связанных с добавлением и удалением продуктов. Мы могли бы хранить ссылку на коллекцию продуктов в Mongo или использовать встроенные документы. У каждого подхода есть свои плюсы и минусы. Мы должны хранить метку времени добавления новых продуктов, чтобы встроенный документ нам больше подходил. Более того, так будет эффективнее.
Мы используем данные о продукте и создаем отдельный ShoppingCartItem
встроенный документ.
Проблема, с которой мы можем столкнуться, - это синхронизация данных между коллекциями. Когда кто-то меняет название продукта, оно не будет автоматически распространяться, и мы увидим устаревшее название в корзине. Нам нужно будет создать собственный механизм для обеспечения согласованности данных.
Мы сохраняем модели с помощью Doctrine Document Manager. Мы можем использовать собственный репозиторий для каждой модели или использовать встроенный с базовыми функциями. Для простоты мы будем придерживаться последнего. Если нам потребуется дополнительная настройка, нам нужно будет добавить параметр repositoryClass
в аннотацию @ODM\Document
.
MongoDB зарекомендовал себя очень полезным во многих случаях использования и может отлично работать с PHP. Это определенно интересная альтернатива для наиболее распространенных движков баз данных в проектах PHP, таких как MySql или PostgreSQL.