Дневник разработки: швы драйверов, баги с URL и настройки в БД
Я провел весь день, создавая платформу. Одна архитектурная идея всплывала постоянно: необходимо проложить «шов» между тем, что вы делаете, и тем, где вы храните данные.
Это позволит вам позже заменить бэкенд, не меняя основной код.
Паттерн «швов»
Я создаю платформу для мониторинга (observability). Она собирает ошибки и метрики из множества источников. Каждая задача по хранению данных следовала одному и тому же паттерну:
• Создать небольшой интерфейс (контракт). • Создать драйвер Eloquent (реализацию).
Дашборды и конвейеры (pipelines) взаимодействуют только с интерфейсом. Сейчас я использую Postgres, так как он надежен. Если позже мне понадобится база данных быстрее, я просто напишу новый драйвер. Мне не придется менять код дашбордов.
Урок прост: вам не нужен второй драйвер в первый же день. Вам нужен интерфейс в первый же день. Один дополнительный файл сейчас избавит от масштабного переписывания кода в будущем.
Три полезные привычки
• Используйте двойную идентификацию. Используйте auto-increment ID для быстрых внутренних соединений (joins). Используйте UUID для всего, что покидает вашу систему, например, для URL или API. Это позволит скрыть реальное количество строк в таблицах.
• Используйте Enums. Храните роли и статусы в PHP enums. Это гарантирует, что ваш UI и ваша логика используют единый источник истины (source of truth).
• Версионируйте данные. Всегда включайте поле версии в полезную нагрузку (payload). Добавляйте новые необязательные поля, но никогда не переименовывайте и не удаляйте старые. Это предотвратит поломку работы старых клиентов.
Баг с отслеживанием URL
Я обнаружил баг в пакете для отслеживания кликов в email-рассылках. Пакет перезаписывает ссылки для отслеживания переходов. Он шифрует URL, а затем восстанавливает его во время редиректа.
Проблема: Laravel экранирует HTML-символы в ссылках внутри email-шаблонов. В подписанной (signed) URL используются символы «&». В HTML они превращаются в «&».
Если вы зашифруете уже экранированную строку, «&» останется в URL. Когда Laravel попытается проверить подпись, проверка не пройдет, так как строка изменилась. Это происходит только с подписанными URL, поэтому баг трудно обнаружить.
Решение: Декодируйте HTML-сущности перед тем, как захватывать URL.
Использование базы данных для конфигурации
Я реализовал возможность для администраторов менять настройки приложения через дашборд. Эти настройки хранятся в базе данных, но приложение по-прежнему считывает их с помощью стандартной функции config().
Я использую тонкую прослойку в AppServiceProvider. Она считывает настройки из базы данных и передает их в config() для текущего запроса. Это позволяет остальному коду оставаться простым и стандартным.
Общая тема здесь — границы. Решите, где должен проходить «шов». Установите границу в правильном месте один раз, и всё остальное будет работать просто.
