Статьи

Как был построен Xmas Sales Back-end

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

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

  • Обслуживайте данные о продажах (информация о сделках) и данные об истории (изображения и анимация) в формате JSON
  • Данные должны быть разными для каждого дня: каждый день содержит не только текущий, но и предыдущие дни (с небольшими изменениями, такими как отключение продажи)
  • Интерфейс администратора для редактирования продаж и замены их в случае необходимости

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

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

Настроить

Symfony2 — это инфраструктура MVC, основанная на множестве компонентов, соединенных вместе. Компоненты управляются composer , менеджером зависимостей для PHP. Используя composer, для запуска Symfony2 требуется всего пара командных строк.

Как только фреймворк готов к использованию, я обычно начинаю с определения сущностей (часть модели MVC). Обычно это означало бы написание большого количества стандартного кода (классы с геттерами / сеттерами для всех полей базы данных), но Symfony2 предоставляет удобные команды CLI для генерации сущностей. Это менее подвержено ошибкам и намного быстрее.

Интерфейс администратора

Вторая утомительная задача — написать интерфейс администратора с формами для создания и редактирования объектов. К счастью, Symfony2 позволяет нам автоматически создавать интерфейс CRUD (создание / чтение / обновление / удаление) с помощью другой команды. Чтобы все выглядело лучше и удобнее, я разработал интерфейс с помощью Twitter Bootstrap .

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

Обслуживание JSON

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

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

Кэширование

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

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

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

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

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

Теперь при создании кэша мы устанавливаем последнее измененное значение на текущий день. Затем при каждом следующем запросе мы сравниваем последнее измененное значение кэша с текущим днем. Если они совпадают, мы обслуживаем кэшированный ответ. С этим кодом мы обращаемся к базе данных только один раз в день (вместо каждого запроса!).

тестирование

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

Для этой задачи мы используем функциональные тесты . Функциональные тесты очень похожи на модульные тесты , но их цель — проверить правильность вывода приложения. Каждый тест имитирует HTTP-запрос и позволяет разработчику выполнять различные проверки возвращаемого ответа. Это очень просто в Symfony2, так как фреймворк моделируется по модели HTTP запрос-ответ , поэтому имитировать запросы очень просто.

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